简介
Vue 最独特的特性之一,是其非侵入性的响应式系统。数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新。让我们将研究一下 Vue 响应式系统的底层的细节。
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
注意点
Vue 不能检测数组和对象的变化。尽管如此vue还是有一些办法来回避这些限制并保证它们的响应性。
对于对象
vue无法检测到对象的属性的增删,由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。如果不存在就无法检测变化;
var vm = new Vue({
data:{
obj:{
a:1
}
})
// `vm.obj.a` 是响应式的
vm.obj.b = 2
// `vm.obj.b` 是非响应式的
为了解决上面的问题,vue提供了Vue.set()或者vm.$set方法
Vue.set(vm.someObject, 'b', 2)
this.$set(this.someObject,'b',2)
有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
对于数组
Vue 不能检测以下数组的变动:
1.当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue 2.当你修改数组的长度时,例如:vm.items.length = newLength
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
为了解决上面的问题,Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
这7个api会自动处理监听和代理,并更新UI,所以数组增删key最好通过这7个api