<p>相信有很多小伙伴早已经对vue的双向数据绑定有一定的了解了~,今天我们就来对比和重温一下vue2和vue3实现双向数据绑定的原理以及他们之前的一些细节问题。</p>
讯享网
首先我们先要明白响应式的底层设计原理:
vue的响应式原理设计三个重要对象:Observer,Watcher,Dep。
Observer对象:vue中的数据对象在初始化过程中转换为Observer对象。
Watcher对象:将模板和Observer对象结合在一起生成Watcher实例,Watcher是订阅者中的订阅者。
Dep对象:Watcher对象和Observer对象之间纽带,每一个Observer都有一个Dep实例,用来存储订阅者Watcher。
当属性变化会执行主题对象Observer的dep.notify方法, 这个方法会遍历订阅者Watcher列表向其发送消息, Watcher会执行run方法去更新视图。
附上一张图帮助大家加深理解,上面这段文字,大家可以联系平时使用vue时的操作,更好理解
讯享网
下面我们再来看看在vue2.0和vue3.0里面是分别是如何实现数据相应式的。
使用Object.defineProperty对象以及对象属性的劫持+发布订阅模式。
语法:
Object.defineproperty( object,‘ propName ’ ,descriptor);
object:要监听的目标对象
propName :要定义或修改的属性的名称。
descriptor:要定义或修改的属性描述符,操作详情。
讯享网
问题1:Object.defineproperty能监听到对象的新增删除属性吗?
不能,需要开发者主动调用相应的方法去更新 :Vue.set(),Vue.delete,由于 Object.defineProperty 劫持的是对象的属性,所以新增属性时,需要重新遍历对象,对其新增属性再使用 Object.defineProperty 进行劫持。
问题2:Object.defineproperty能监听到数组的添加删除操作吗?
不能,依然可以Vue.set(),Vue.delete更新数据,看到这里,可能有些同学就会有疑问,那为啥我在项目中给数据使用push给数组添加一个数据,不需要调用set,页面能够更新响应呢,那是因为vue2.0使用数组重写的方法实现了数组的响应,7个方法分别为 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'。
问题3:如果我只是改变数组的索引的值,例如:vm.items[indexOfItem] = newValue真的不能被监听么?
答案是:能,Object.defineProperty能监听到,那为啥vue不给添加监听呢,因为性能对于对象而言,每一次的数据变更都会对对象的属性进行一次枚举,一般对象本身 的属性数量有限,所以对于遍历枚举等方式产生的性能损耗可以忽略不计,但是对于数组而言呢?数组包含的元素量是可能达到成千上万,假设对于每一次数组元素的更新都触发了枚举/遍历,其带来的性能损耗将与获得的用户体验不成正比,故vue无法检测数组的变动。
再者注意:Object.defineProperty()是深度监听,需要递归到底。一次性计算量很大。
vue3.0实现数据的响应式是通过 Proxy。
与Object.defineProperty不同 的是Object.defineProperty只能劫持对象的属性,而Proxy是直接代理对象。因为proxy是对整个对象进行代理,所以可以监听对象某个属性值的变化,还可以监听对象属性的新增和删除,而且还可以监听数组。
proxy是ES6的新增的功能,可以用来定义对象中的操作
基本语法:
proxy是对整个对象进行代理,不关心对象里面具体有什么属性,而defineProperty只能响应首次渲染时候的属性,但是proxy的兼容性不好,IE无法兼容,vue2是兼容到了IE8,但是vue3使用了proxy说明放弃了对IE的兼容考虑。
下面我们分别手写Object.defineProperty,proxy监听一个对象的实现。
Object.defineProperty
讯享网
proxy:
建议想要真正了解 Object.defineProperty 和 proxy 是如何实现数据监听的小伙伴,可以自己手动实现下,对监听的过程加深理解

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/181714.html