一、Vue的data是响应式的。
const vm = new Vue({data : {n : 0}})
上述代码,如果修改vm.n,那么UI中的n就会响应。Vue通过Object.defineProperty来实现数据响应式。
二、Vue的bug
1. Object.defineProperty的问题
Object.defineProperty(obj , 'n' , {...})中必须要有一个'n'才能监听和代理obj.n,如果没给n,Vue会报错,但Vue只会检查第一层属性,有多层的话警告会消除,但不会转为响应式,因为Vue无法监听不存在的数据。如:
new Vue({
data: {
obj: {
a: 0 // obj.a 会被 Vue 监听 & 代理
}
},
template: `
<div>
{{obj.b}}
<button @click="setB">set b</button>
</div>
`,
methods: {
setB() {
this.obj.b = 1; //此时虽然不报错,但页面中不会显示1
}
}
}).$mount("#app");
此种情况有两种解决方法:
- 把
key都声明好,后面不再加属性即可:
- 使用
Vue.set或者this.$set新增Key、自动创建代理和监听并触发UI更新:
2. 如果data中有数组,你无法提前声明所有key
数组的长度可以一直增加,下标就是key,难道每次改数组都要用Vue.set或者this.$set(而且用Vue.set或this.$set不会创建代理和监听)?Vue有法子:
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()pop()shift()unshift()splice()sort()reverse()
举例:
new Vue({
data: {
array: ["a", "b", "c"]
},
template: `
<div>
{{array}}
<button @click="setD">set d</button>
</div>
`,
methods: {
setD() {
this.array.push("d") //变异API
console.log(this.array);
}
}
}).$mount("#app");