数据响应式举例个来说就是,一个物体对于外界的刺激能够做出相应的反应。使用 Vue进行开发时,一旦页面上的数据在 JS内进行了跟新,不需要开发者修改渲染的代码,Vue会自动进行跟新。
这是因为Vue在实例化声明数据时进行了监听和代理,若数据发生了改变,会监听到变化对此进行重新渲染。
Vue如何实现数据响应式
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。 这个getter/setter对于用户是不可见的,但在内部它们让Vue能够追踪依赖,在 property 被访问和修改时通知变更。
let vm = new Vue({
data: {
obj: {
a: 0
}
}
})
举例代码如上,通过Object.defineProperty()将a的数据转为 getter/setter。若是要对data内声明的数据进行更改。现实实例vm就是data的代理,通过vm可以更改data。
vm.obj.a = 2 // 可以更改
this.obj.a = 2 // 可以更改
this.data.obj.a = 2 // 不可以更改
注意事项
由于JS的限制,Vue对于数组和对象的变化的检查有些问题。
关于对象
- 示例一
new Vue({
data: {},
template: `
<div>{{n}}</div>
`
}).$mount("#app");
n不存在,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;
}
}
}).$mount("#app");
页面中点击按钮不会出现1,这是因为Vue只会检查第一次属性。
解决方法:
1.在obj内声明b
2.使用Vue.set()/this.$set()
methods:{
setB(){
Vue.set(obj, 'b', 2)
// this.$set(this.obj,'b',2)
}
}
关于数组
Vue不能检测以下数组变动
1.利用索引直接设置一个数组项
2.修改数组长度
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不响应
vm.items.length = 2 // 不响应
解决方法:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
当数据中含有数组时,若要给数组添加元素,但新增元素的index在声明实例的时候还未定义,为了解决这个问题,Vue的作者将数组的七个方法进行了变更。对Array()函数通过继承,增加了一条原型链的环节,并在环节中添加了七种方法,方法的内部进行了Vue.set()的操作,使的数组的新元素能被实例化。
变更方法
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
- push()
参考来自 Vue文档——深入响应式原理