什么是数据响应式
- 简单来说,响应式就是当修改了vm中的数据时,Vue会通知到使用该数据的代码,自动更新视图。
- 例如:
const vm = new Vue ({
data:{n:0}
})
在上面的代码中,vm相当于data的代理,当修改vm.n或data.n(数据改变)时,UI中的n就会做出响应,该联动过程即为Vue的数据响应式。
Object.defineProperty
Vue2是通过Object.defineProperty()方法来实现数据响应式的。
let vm = new Vue({
data: {
obj: {
a: 0
}
}
})
以上代码举例,会通过Object.defineProperty()将a用一个含getter/setter的虚拟属性替代,这样就实现对a数据的读写和监听。 再通过在data外层包裹一层代理(一层包含getter/setter虚拟属性的对象),实现实例对象vm对data的代理。即必须通过vm更改data内已声明的数据。
vm.obj.a = 2 //可以更改
this.obj.a =2 //可以更改
this.data.obj.a =2 //不可以更改
新增属性
当我们以普通的方式增添新数据(实例化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; //页面中不会渲染出b值,因为b未被Vue监听
}
}
}).$mount("#app");
上述代码中只有obj.a会被监听,这时候去更改obj.b就没有效果,因为obj.b在一开始就没有写在数据里。
解决办法:
- 在不事先声明key的情况下,增加属性的方法有
Vue.set和this.$set两者等价。 - 这两个api都可以新增key,同时创建代理和监听,并触发UI更新。
代码示例:
methods: {
setB() {
Vue.set(obj,"b",1)
}
}
新增数组
当数据中含有数组时,当我们想为数组添加元素时,新增元素的index在声明实例时未定义,也会面临相同的情况(数组是一种特殊的对象,property为数字的对象)。此时我们也应该采取一些措施,好在vue的作者为我们将数组的七种方法进行了变异,这七种方法分别是
- pop()
- push()
- shift()
- unshift()
- splice()
- splice()
- sort()
- reverse()
Vue作者为Array()函数通过继承,新增了一条原型链环节,在该环节中添加了上述七种方法,并方法内部进行了Vue.set()方法的操作,使数组的新元素可以被Vue实例对象监听和代理。