响应式原理

Vue中的响应式通过三种响应式解决方案,defineProperty、Proxy、value setter。

Vue2中使用 defineProperty API 实现响应式,存在的缺陷就是删除 obj.count 属性,set 函数不会执行,所以Vue2中需要使用
$delete 函数区删除数据。如下代码实现了简易的响应式功能,定义一个对象obj,使用 defineProperty 代理了 count 属性。这就实现了
obj 对象的 value 属性实现了拦截,读取 count 属性的时候执行 get 函数,修改 count 属性的时候 set 函数,并在 set
函数内部重新计算了 double 。
let getDouble = n=>n*2 let obj = {} let count = 1 let double =
getDouble(count) Object.defineProperty(obj,'count',{ get(){ return count },
set(val){ count = val double = getDouble(val) } }) console.log(double) // 2
obj.count = 2 console.log(double) // 4
Vue3 的响应式机制是基于 Proxy 实现的,解决了 Vue2 响应式的缺陷。如以下代码, 通过 new Proxy 代理了 obj 对象,然后通过
get、set、deleteProperty 函数代理了对象的读取、修改和删除操作,从而实现了响应式的功能。
let getDouble = n=>n*2 let obj = {} let count = 1 let double =
getDouble(count) let proxy = new Proxy(obj, { get : function (target, prop) {
return target[prop] }, set : function (target, prop, value) { target[prop] =
value; if(prop === 'count') { double = getDouble(value) } },
deleteProperty(target, prop) { delete target[prop] if(prop === 'count') {
double = NaN } } }) console.log(obj.count, double) // undefined 2 proxy.count =
2 console.log(obj.count, double) // 2 4 delete proxy.count
console.log(obj.count, double) // undefined NaN
Vue3 Proxy 实现的功能和 Vue2 的 definePropery 类似,都能够在用户修改数据的时候出发 set 函数,更新 double
,Proxy 还完善了 definePropery 的缺陷,如监听属性的删除。Proxy
是针对对象来监听,而不是针对某个具体属性,所以不仅可以代理定义时不存在的属性,还可以代理更丰富的数据结构,比如 Map、Set ...,还能通过
deleteProperty 实现对删除操作的代理。

Vue3 除了 Proxy 还有另一个响应式实现的逻辑,利用对象的 get 和 set
函数来进行监听,这种响应式的实现方式,只能拦截某一个属性的修改,这也是 Vue3 中 ref 这个 API 实现的。如下代码中,拦截了 count
的value 属性,并且拦截了 set 操作,也能实现类似的功能。
let getDouble = n=>n*2 let _value = 1 double = getDouble(_value) let count = {
get value() { return _value }, set value(val) { _value = val double =
getDouble(_value) } } console.log(count.value, double) // 1 2 count.value = 2
console.log(count.value, double) // 2 4
这三种实现原理对比如下:

实现原理definePropertyProxyvalue setter
实际场景Vue2 响应式Vue3 reactiveVue3 ref
优势兼容性基于Proxy实现真正的拦截实现简单
劣势数组和属性删除等拦截不了不兼容IE11只拦截了value属性
实际应用Vue2Vue3 复杂数据结构Vue3 简单数据结构

技术
下载桌面版
GitHub
百度网盘(提取码:draw)
Gitee
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:766591547
关注微信