【拆解Vue3】reactive是如何实现的?(下篇)

本文详细探讨了Vue3中reactive的实现,包括如何处理for…in循环的响应式,删除响应式对象属性的方法,浅响应与深响应的区别,以及如何创建只读的响应式对象。文章通过实例分析了响应式原理,揭示了Vue3响应式系统的关键细节。
摘要由CSDN通过智能技术生成

响应式中的for…in

在Vue中,我们也可以在副作用函数中使用for…in循环来枚举响应式对象的属性。

const data = {foo: 1
}
const obj = reactive(data)
effect(() => {for(const key in obj) {console.log(key)}
}) 

在JavaScript中,任何操作的底层实现都基于基本语义方法,for…in也不例外。在for…in中,使用了Reflect.ownKeys(obj)来获取只属于对象自身的属性名,因此,我们可以在Proxy中利用ownKeys(),来对for…in的Reflect.ownKeys(obj)进行拦截。

const bothNaN = (newValue, oldValue) => !(newValue === newValue || oldValue === oldValue)
const isEqual = (newValue, oldValue) => bothNaN(newValue, oldValue) || oldValue === newValue
function reactive(obj) {return new Proxy(obj, {get(target, key, receiver) {track(target, key)if(key === 'raw') {return target}return Reflect.get(target, key, receiver)},set(target, key, newValue, receiver) {const oldValue = target[key]if(target === receiver.raw && !isEqual(newValue, oldValue)) {target[key] = newValuetrigger(target, key)}return Reflect.set(target, key, newValue, receiver)},ownKeys(target) { // (1)track(target, ITERATE_KEY) // (2)return Reflect.ownKeys(target)}})
} 

在(1)处,我们按照之前的思路,增加了拦截函数ownKeys(target)。但在拦截收集副作用函数的时候犯了难,ownKeys仅能拦截到target对象,无法拦截具体的key。因此,我们需要把key补上,同时能够满足key是唯一的,这里可以使用Symbol()生成全局唯一的key,供track收集指定的for…in副作用函数。在(2)处,我们引入了Symbol类型的值ITERATE_KEY来唯一表示for…in副作用函数。

然而,当我们尝试运行修改后的代码,reactive还是无法实现对for…in的响应式。仔细想想也能够理解,我们在收集的时候,keySymbol类型的ITERATE_KEY,而我们修改的是obj.foo,此时触发的keyfoo而不是ITERATE_KEY。所以,我们需要修改触发部分的逻辑,当全局的ITERATE_KEY存在时,ITERATE_KEY对应的副作用函数也应该被触发。

function trigger(target, key) {const propsMap = objsMap.get(target)if(!propsMap) returnconst fns = propsMap.get(key)const iterateFns = propsMap.get
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值