从源码分析vue2和vue3的响应式区别(二)

138 篇文章 1 订阅
138 篇文章 1 订阅

接着上一篇我们提到的vue2的响应式原理,我们这篇文章将聊聊vue3的响应式原理。

vue3 的响应式核心

vue3 的响应式核心就是proxy代理。它与vue2中的Object.defineProperty作用类似,都是将数据拦截下来,也就是在设置对象属性或者读取对象属性时做一层拦截操作。但是最大的不同之处在于proxy是创建一个对象的代理,并不是在原对象上进行改变,而 Object.defineProperty 是直接在原对象上修改或定义属性。

proxy的使用

Proxy 是 ES6 中新增的一个函数,但 Proxy 本质就是一种构造器,我们要通过 new 去实现的。如

 

js

代码解读

复制代码

let observed = new Proxy(target, baseHandler)

它有两个参数,分别代表被代理的对象以及处理器对象,也就是进行各种操作的对象。处理器对象中包含多个方法,如:

  1. get(target, key, receiver):读取代理对象的某个属性时触发该操作
  2. set(target, propKey, value, receiver) :给代理对象的某个属性赋值时触发该操作
  3. has(target, propKey) :用于判断代理对象是否拥有某个属性时触发
  4. deleteProperty(target, propKey): 删除代理对象的某个属性时触发该操作 等等···

我们在响应式中需要用到的就是set()和get()。

get方法有三个参数get(target, key, receiver)分别为目标对象、键、实例对象本身

set方法有四个参数 set(target, key, value, receiver),分别为目标对象、键、值、实例对象本身。

具体的用法就如下所示:

 

js

代码解读

复制代码

let baseHandler = { get(target, key, receiver) { console.log('读取'); let result = Reflect.get(target, key) // target[key] return isObject(result) ? reactive(result) : result // 递归 }, set(target, key, value, receiver) { console.log('修改'); return Reflect.set(target, key, value, receiver) // 将target中的key值修改为value } }

在这里需要注释一下Reflect对象,Reflect其实与我们常用的Object对象并无太大差异,它设计初衷是为了支持 Proxy,使得 Proxy 的处理器对象能够更方便地调用标准的操作。Reflect 提供了一组静态方法,用于直接操作对象,同时保持与 Proxy 操作的一致性。具体的差异大家可以自行查看一下资料。

另外proxy也不能深层代理对象,所以仍需和Object.defineProperty一样进行递归。但是它与之不同的是只用在用到的时候进行递归,而不是无脑的默认递归。

Proxy对象可以拦截13种不同的操作,所以它不会有Object.defineProperty无法数组进行拦截,以及对不存在的属性进行拦截的困扰。这大大的减少了vue3的源码代码量,使之更简洁也更易懂。

vue3 响应式源码

vue3的响应式核心就是proxy,其他的与vue2较为类似,知识不需要再额外的对数组进行操作。但是在vue3的响应式中,我们需要考虑被代理后的对象不需要重复代理以及对象是否被二次代理过。。尤达大这一部分考虑进去了确实减少了很多的性能开销,因为只用被代理一次就行了。

在这个问题上用的解决方法是是WeakMapWeakSet,具体的请,如下代码片段:

 

js

代码解读

复制代码

// 判断是否被代理了 let proxy = toProxy.get(target) if (proxy) { return proxy } // 判断代理对象是否被二次代理过 if (toRow.has(target)) { return target } // 对象代理 let observed = new Proxy(target, baseHandler) toProxy.set(target, observed) toRow.add(observed, target)

总结

vue3的响应式还是很简洁的,但是它解决了vue2响应式中存在的问题,包括不能处理数组,不能处理数组上的length属性,以及对象上不存在的属性劫持。

原文链接:https://juejin.cn/post/7412672705302495243

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值