什么是响应式
“响应式”,是指当数据改变后,Vue 会通知到使用该数据的代码。例如,视图渲染中使用了数据,数据改变后,视图也会自动更新。
举个简单的例子,对于模板:
<div id="root">{{ name }}</div>
复制
创建一个 Vue 组件:
var vm = new Vue({
el: '#root',
data: {
name: 'luobo'
}
})
复制
代码执行后,页面上对应位置会显示:luobo。
如果想改变显示的名字,只需要执行:
vm.name = 'tang'
复制
这样页面上就会显示修改后的名字了,并不需要去手动修改 DOM 更新数据。
响应式原理
Vue 的响应式原理是核心是通过 ES5 的保护对象的 Object.defindeProperty 中的访问器属性中的 get 和 set 方法,data 中声明的属性都被添加了访问器属性,当读取 data 中的数据时自动调用 get 方法,当修改 data 中的数据时,自动调用 set 方法,检测到数据的变化,会通知观察者 Wacher,观察者 Wacher自动触发重新render 当前组件(子组件不会重新渲染),生成新的虚拟 DOM 树,Vue 框架会遍历并对比新虚拟 DOM 树和旧虚拟 DOM 树中每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真实 DOM 树上。

响应式缺陷
vue不能监听数组的变化
Object.defindProperty虽然能够实现双向绑定了,但是还是有缺点,只能对对象的属性进行数据劫持,所以会深度遍历整个对象,不管层级有多深,只要数组中嵌套有对象,就能监听到对象的数据变化无法监听到数组的变化,Proxy就没有这个问题,可以监听整个对象的数据变化,所以用vue3.0会用Proxy代替definedProperty。
Vue不能检测到对象属性的添加或删除
受现代JS的限制(以及废弃 Object.observe),Vue不能检测到对象属性的添加或删除,由于Vue会在初始化实例时对属性执行 getter/setter转化过程,所以属性必须在data对象上存在才能让Vue转换它,这样才能让它是响应的。
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应的
vm.b = 2
// `vm.b` 是非响应的
复制
Vue不允许在已经创建的实例上动态添加新的根级响应式属性(root-level reactive property),然而它可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上。
Vue.set(vm.someObject, 'b', 2)
复制
也可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名。
this.$set(this.someObject,'b',2)
复制
有时想向已有对象上添加一些属性,例如使用Object.assign()或 _.extend()方法来添加属性。但是,添加到对象上的新属性不会触发更新。在这种情况下可以创建一个新的对象,让它包含原对象的属性和新的属性。
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
复制