关于自学vue3响应式源码-proxy中的一个问题(Reflect.set)
最近在看vue3响应式源码,自己手写时发现了一个情况是
export const reactive = (target) => {
return new Proxy(target, {
get(target, prop, recevier) {
//依赖收集
track(target, prop);
return Reflect.get(...arguments);
},
set(target, prop, value, recevier) {
let res = Reflect.set(...arguments);
//触发依赖更新
trigger(target, prop);
//这里如果直接return Reflect.set(...arguments),则会有更新问题
//比如在setTimeout中同时更新一个对象的两个属性,则计时器结束之后只会更新第一个属性,第二个不触发更新
//先赋值res,再返回,则正常
return res;
},
})
}
let animal = reactive(
{
name: 'dog',
age: 2
}
)
effect(() => {
document.querySelector('#app').innerHTML = `
<div>
<h2>name: ${animal.name}</h2>
<h2>age: ${animal.age}</h2>
</div>
`
})
setTimeout(()=>{
animal.name = 'cat'//更新
animal.age = 3//直接return Reflect.set不会更新
},2000)
改为let res = Reflect.set(...arguments);再返回则正常
animal.name = 'cat'
首次trigger
时,animal
对象还未更新,拿到的是{name: 'dog', age: 2}
, 执行完effect
后,使用Reflect.set(...arguments)
进行设置,变为了{name: 'cat', age: 2}
;animal.age = 3
再次trigger
时,拿到的animal
值为{name: 'cat', age: 2}
,表现为“第二个不触发更新”,最后使用不触发更新的Reflect.set(...arguments)
进行设置,变为了{name: 'cat', age: 3}
,页面无变化