vue响应式原理

vue的响应式,数据模型仅仅是普通的Javascript对象。当你修改它们时,视图会进行更新

那么如何追踪变化:

当把普通的js对象传给vue实例的data选项,Vue将遍历此对象的所有属性,并使用Object.defineProperty把这些属性全部转为getter/setter。

这些getter/setter对用户是不可见的,在内部它们让Vue追踪依赖,在属性被访问和修改时通知变化。

每个组件实例都有相应的watcher实例对象,它会在组件渲染过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而导致使它关联的组件得以更新。

属性必须在data对象上存在才能让vue转化它,vue不允许在已经创建的实例上动态添加新的根级响应式属性。然而它可以使用Vue.set(object,key,value)方法将响应属性添加到嵌套的对象上。

还可以使用Vm.$set实例方法,这是全局Vue.set方法的别名:

例如:
this.$set(this.someObject,'b',2)

有时想向一个已有对象添加多个属性,例如使用Object.assign()或者_.extend()方法来添加属性。但是,这样添加到对象上的新属性不会被触发更新。

解决办法:创建一个新的对象,让它包含原对象的属性和新的属性:

this.someObject=Object.assign({},this.someObject,{a:1,b:2})

声明响应式属性:

由于vue不允许动态添加根级响应式属性,所以必须在初始化实例前声明根级响应式属性,哪怕只是一个空值:

var vm=new Vue({
data:{
message:''
},
template:'<div>{{message}}</div>'
})
vm.message='1'

 如果你未在 data 选项中声明 message,Vue 将警告你渲染函数正在试图访问的属性不存在。

它消除了在依赖项跟踪系统中的一类边界情况,使得Vue实例在类型检查系统的帮助下运行得更高效。

代码在可维护性方面有一点重要考虑:data对象像组件状态的概要,提前声明所有的响应式属性,可以让组件代码在以后重新使用更方便

异步更新队列:

Vue异步执行dom更新。只要观察到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个watcher将被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作是非常重要的。然后,在下一个事件循环‘tick’中,Vue刷新队列并执行实际工作。Vue在内部尝试对异步队列使用原生的promise.then,如果执行环境不支持,会采用setTimeout(fn,0)

当设置了vm.someData='new value',该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个tick更新。为了在数据变化之后等待vue完成更新dom,可以在数据变化之后立即使用Vue.nextTick(cb).这样回调函数在dom更新完成后就会调用。

this.$nextTick()返回一个promise对象。

原文地址:https://www.cnblogs.com/yuan233/p/10693047.html