本文只是对官网的总结以及一些个人理解,方便自己查阅
# data
data对象定义必须通过工厂函数返回一个对象(避免所有实例引用同一个对象)。
通过 this.a 或者 this.$data.a 访问。
尽量在创建实例之前,就声明所有的根级响应式属性。(Vue 不能检测到对象属性的添加或删除。),如果没有在 data 中事先声明而直接使用,Vue 会警告访问的属性不存在。
1
2
3
4
5
6
7
8
9
10
11var vm = new Vue({
data:{
a:1,
obj: {}
}
})
// `vm.a` 是响应的
vm.b = 2
// `vm.b` 是非响应的data 属性使用箭头函数,this 不会指向这个组件的实例,但是可以通过函数的第一个参数来访问。
1
data: th => ({ a: th.myProp })
可以使用 Vue.set(object, key, value) 方法将响应属性添加到已有的对象上。
1
Vue.set(vm.obj, 'b', 2);
或者:
1
2
3
4
5
6/* data:{
a:1,
obj: {'b': '1'}
};*/
this.$set(this.obj,'b',2); // 改变已有属性,不会触发watch, 需加上deep属性(详见watch)。
this.$set(this.obj,'d',2); // 新增属性,可直接触发watch。亦或:
1
2// 通过创建一个新的对象,来触发响应式变化,watch检测的时候很有用。
this.obj = Object.assign({}, this.obj, { a: 1, b: 2 }); // 改变了引用地址,触发watch。
# props
props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义校验和设置默认值。
普通用法
1
2// 简单语法
props: ['info', 'data'];推荐用法
1
2
3
4
5
6props: {
age: {
type: Number, // 指定类型,String、Number、Boolean、Function、Object、Array、Symbol
default: 0 // type为对象或数组时,default需要用工厂函数返回
}
}自定义验证
1
2
3
4
5
6propF: {
validator: function (val) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'info'].indexOf(val) !== -1
}
}验证构造函数
1
2
3
4
5
6
7
8
9
10
11/*
function Person (name) {
this.name = name;
this.talk = function() {
alert(name);
}
}
*/
props: {
pepole: Person // 来验证 pepole 的值是否是通过 new Person 创建的。
}props 的数据传递是单向的,父级的数据更新会传递给子级,反之则不行。也不允许在子组件中直接改变props的传值。
这样可以防止从子组件意外改变父级组件的状态,否则导致你的应用的数据流向难以理解。组件中推荐的数据流导向,父 ——> 子:porps;子 ——> 父 :事件($emit);
但是对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。
也就是说允许改变prop传入对象的某个属性,或者数组中的某个元素,但不允许更改引用类型的地址。非引用类型,不允许改变。
1
2
3
4
5
6
7
8
9// list: ['a', 'b', c'];
props: ['list'],
computed: {
clist() {
this.list.pop(); // 允许
this.list = ['a', 'b']; // 不允许
return this.list;
}
}prop 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
(即,在 default 或 validator 函数中,不能用data、computed中的数据)。
# computed
计算属性,用以定义一些需要逻辑处理得到的数据,计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。
计算属性使用了箭头函数,则 this 不会指向这个组件的实例,但是可以将其实例作为函数的第一个参数来访问,同data;
1
2
3computed: {
aDouble: th => th.a * 2
}直接以this.now访问或者now()函数调用。二者区别是,前者只有在响应式依赖改变时才会更新,而方法调用每次都会重新执行。
1
2
3
4
5
6// Date.now() 不是响应式依赖,所以缓存后不会触发更新。此时就应选择now()访问;
computed: {
now: function () {
return Date.now()
}
}计算属性默认只有getter,但是也可以通过setter来设置。
1
2
3
4
5
6
7
8
9
10
11
12computed: {
date: {
get: function () {
return Date.now();
},
set: function (date) {
this.customDate = new Date(date).getTime();
}
}
}
// this.date = '2018-01-01';
// this.customDate // => 1514764800000计算属性与侦听属性在某些情况很相似,然而当你有一些数据需要随着其它数据变动而变动时,有时候计算属性表现更为优秀,而不是滥用watch。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20data(
return {
a: 0,
b: 1,
totalY: 0
}
),
computed: {
total() {
return this.a + this.b;
}
},
watch: { // 显然,计算属性要更简洁
a(val) {
this.totalY = val + this.b;
},
b(val) {
this.totalY = val + this.a;
}
}
# watch
侦听属性,侦听数据变化,用以在某些数据改变时,进行相应操作。
基础用法,第一个参数是改变后的值,第二个是改变前的值;
1
2
3
4
5
6
7
8
9
10
11a: function (val, oldVal) {
console.log(this, val);
}
b(val, oldVal) {
console.log(this, val);
}
c: (val, oldVal) => {
console.log(this, val);
}
// b的写法不过是a的语法糖,两者是一样的。但是c用到了箭头函数,此时的this,已经不是vue实例了。
// 所以不应该使用箭头函数来定义watch函数,methods跟这个情况一样,也不能使用箭头函数。写一个方法名,检测到相应值变化时会直接调用方法;
1
2
3
4
5b() {
this.myMethod();
}
b: 'myMethod'
// 二者一样deep,深度watch,设为 true 可以检测到对象属性的变化(注:obj.a = ‘new’,这种赋值方式依然不响应;适用于$set);
1
2
3
4c: {
handler: function (val, oldVal) { console.log(val, oldVal) },
deep: true
}immediate,设为 true 将会在侦听开始之后被立即调用(即,会在初始化时调用一次);
1
2
3
4d: {
handler: function (val, oldVal) { console.log(val, oldVal); },
immediate: true
}多个检测函数;
1
2
3
4e: [
function handle1 (val, oldVal) { console.log(val, oldVal); },
function handle2 (val, oldVal) { console.log(val, oldVal); }
]直接检测对象某个属性的值变化;
1
'obj.a': function (val, oldVal) { console.log(val, oldVal); }