为什么在Vue3响应式源码中,使用Reflect.set时先赋值再返回能够解决更新问题?
关于自学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);再返回则正常
回复
1个回答

test
2024-06-18
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}
,页面无变化
回复

适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容