深入响应式原理

一、如何追踪变化
    当你把一个普通的JavaScript对象传给Vue实例的data选项,Vue将遍历此对象所有的属性,并使用Object.defineProperty把这些属性全部转为getter/setter。Object.defineProperty是ES5中一个无法shim(shim可以将新的API引入到旧的环境中,而且仅靠就环境中已有的手段实现。)的特性,这也就是为什么Vue不支持IE8以及更低版本浏览器。
    这些getter/setter对用户来说是不可见的,但是在内部它们让Vue追踪依赖,在属性被访问和修改时通知变化。这里需要注意的问题是浏览器控制台在打印数据对象时getter/setter的格式化并不同,所以你可能需要安装vue-devtools来获取更加友好的检查接口。
    每个组件实例都有相应的watcher实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知 watcher重新计算,从而致使它关联的组件得以更新。
二、检测变化的注意事项
    受现代JavaScript的限制 (而且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 })

 

posted @ 2019-03-22 10:51  leslie-cheung  阅读(155)  评论(0编辑  收藏  举报