Vue.js 设计与实现
霍春阳(HcySunYang)
Vue.js 官方团队成员
340 人已学习
立即订阅
Vue.js 设计与实现
15
15
1.0x
00:00/00:00
登录|注册

第 5 章 非原始值的响应式方案(2)

5.4 合理地触发响应

上一节中,我们从规范的角度详细介绍了如何代理对象,在这个过程中,处理了很多边界条件。例如,我们需要明确知道操作的类型是 'ADD' 还是 'SET',抑或是其他操作类型,从而正确地触发响应。但想要合理地触发响应,还有许多工作要做。
首先,我们来看要面临的第一个问题,即当值没有发生变化时,应该不需要触发响应才对:
const obj = { foo: 1 }
const p = new Proxy(obj, { /* ... */ })
effect(() => {
console.log(p.foo)
})
// 设置 p.foo 的值,但值没有变化
p.foo = 1
如上面的代码所示,p.foo 的初始值为 1,当为 p.foo 设置新的值时,如果值没有发生变化,则不需要触发响应。为了满足需求,我们需要修改 set 拦截函数的代码,在调用 trigger 函数触发响应之前,需要检查值是否真的发生了变化:
const p = new Proxy(obj, {
set(target, key, newVal, receiver) {
// 先获取旧值
const oldVal = target[key]
<pre><code> const type = Object.prototype.hasOwnProperty.call(target, key) ? 'SET' : 'ADD'
const res = Reflect.set(target, key, newVal, receiver)
// 比较新值与旧值,只要当不全等的时候才触发响应
if (oldVal !== newVal) {
trigger(target, key, type)
}
return res
</code></pre>
如上面的代码所示,我们在 set 拦截函数内首先获取旧值 oldVal,接着比较新值与旧值,只有当它们不全等的时候才触发响应。现在,如果我们再次测试本节开头的例子,会发现重新设置相同的值已经不会触发响应了。
然而,仅仅进行全等比较是有缺陷的,这体现在对 NaN 的处理上。我们知道 NaNNaN 进行全等比较总会得到 false
NaN === NaN // false
NaN !== NaN // true
换句话说,如果 p.foo 的初始值是 NaN,并且后续又为其设置了 NaN 作为新值,那么仅仅进行全等比较的缺陷就暴露了:
const obj = { foo: NaN }
const p = new Proxy(obj, { /* ... */ })
effect(() => {
console.log(p.foo)
})
// 仍然会触发响应,因为 NaN !== NaN 为 true
p.foo = NaN
这仍然会触发响应,并导致不必要的更新。为了解决这个问题,我们需要再加一个条件,即在新值和旧值不全等的情况下,要保证它们都不是 NaN
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了非原始值的响应式方案中触发响应的相关问题,包括值未发生变化时不需要触发响应、NaN值的比较问题、从原型上继承属性的情况以及如何确保合理地触发响应。文章特别强调了如何区分浅响应和深响应,并给出了相应的代码示例。另外,还介绍了只读和浅只读的实现方法,以及代理数组的相关操作。通过具体的代码示例和技术原理分析,帮助读者深入理解非原始值的响应式方案中触发响应的相关问题。文章内容丰富,深入浅出,适合对非原始值的响应式方案感兴趣的读者阅读学习。文章内容涵盖了对数组的操作、数组的索引与length属性、遍历数组等多个方面,为读者提供了全面的技术知识和实用的代码示例。文章还介绍了如何处理隐式修改数组长度的原型方法,通过重写数组的push方法等方式解决了相关问题,为读者呈现了一种解决技术问题的思路和方法。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Vue.js 设计与实现》
立即购买
登录 后留言

精选留言

由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论
显示
设置
留言
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部