当前位置: 首页 > news >正文

《Vuejs设计与实现》第 5 章(非原始值响应式方案) 中

目录

5.4 合理触发响应

5.5 浅响应与深响应

5.6 只读和浅只读


5.4 合理触发响应

为了合理触发响应,我们需要处理一些问题。

首先,当值没有变化时,我们不应该触发响应:

const obj = { foo: 1 }
const p = new Proxy(obj, { /* ... */ })effect(() => {console.log(p.foo)
})// 设置 p.foo 的值,但值没有变化
p.foo = 1
 

上述代码,p.foo 的初始值为 1,当为 p.foo 设置新的值时,如果值没有发生变化,则不需要触发响应。
为了满足需求,在调用 trigger 函数触发响应之前,我们需要检查值是否发生了变化

const p = new Proxy(obj, {set(target, key, newVal, receiver) {// 先获取旧值const oldVal = target[key]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}
})

在 set 函数内,先获取旧值 oldVal,比较新旧值,只有不全等时才触发响应。
但是,全等比较对 NaN 的处理有缺陷,因为 NaN === NaN 返回 false,为了解决这个问题,需要加一个条件:

const p = new Proxy(obj, {set(target, key, newVal, receiver) {// 先获取旧值const oldVal = target[key]const type = Object.prototype.hasOwnProperty.call(target, key) ? 'SET' : 'ADD'const res = Reflect.set(target, key, newVal, receiver)// 比较新值与旧值,只有当它们不全等,并且不都是 NaN 的时候才触发响应if (oldVal !== newVal && (oldVal === oldVal || newVal === newVal)) {trigger(target, key, type)}return res}
})

现在,我们已经解决了对 NaN 的处理问题。当新旧值不全等且不都是 NaN 时,才触发响应。

我们还需要处理从原型上继承属性的情况。首先,我们封装一个 reactive 函数,接受一个对象作为参数,返回创建的响应式数据:

function reactive(obj) {return new Proxy(obj, {// 省略拦截函数})
}

接下来,创建一个例子:

const obj = {}
const child = reactive(obj)
const proto = { bar: 1 }
const parent = reactive(proto)
// 使用 parent 作为 child 的原型
Object.setPrototypeOf(child, parent)effect(() => {console.log(child.bar) // 1
})
// 修改 child.bar 的值
child.bar = 2 // 会导致副作用函数重新执行两次

在这个例子中,我们创建了两个响应式对象 child 和 parent,并将 parent 设置为 child 的原型。
在副作用函数中访问 child.bar 时,值是从原型上继承的。当我们执行 child.bar = 2 时,副作用函数会执行两次,导致不必要的更新。
我们分析下整个过程,访问 child.bar 时,触发 child 代理对象的 get 拦截函数。在拦截函数中,引擎使用 Reflect.get(target, key, receiver) 得到结果。如果对象自身

相关文章:

  • 手机换地方ip地址会变化吗?深入解析
  • 开发工具分享: Web前端编码常用的在线编译器
  • 支持向量机算法
  • C++GO语言微服务之Dockerfile docker-compose
  • 深入理解Embedding Models(嵌入模型):从原理到实战(下)
  • 针对面试-mysql篇
  • 洛谷 P1955 [NOI2015] 程序自动分析
  • FPGA----petalinux开机启动自定义脚本/程序的保姆级教程(二)
  • 人工智能100问☞第21问:神经网络如何模拟人脑结构?
  • The Graph:区块链数据索引的技术架构与创新实践
  • 探索大语言模型(LLM):国产大模型DeepSeek vs Qwen,谁才是AI模型的未来?
  • 2025 年福建省职业院校技能大赛网络建设与运维赛项Linux赛题解析
  • 高速边坡监测成本高?自动化如何用精准数据省预算?
  • Java 语法基础(笔记)
  • element plus el-table多选框跨页多选保留
  • Flutter - UIKit开发相关指南 - 控制器,主题,表单
  • Java SpringMVC 和 MyBatis 整合关键配置详解
  • LeetCode 373 查找和最小的 K 对数字题解
  • mysql全量、增量备份与恢复
  • 字节后端开发一面面经
  • 英媒:英国首相住所起火,目前无人伤亡
  • 城市轨道交通安全、内河港区布局规划、扎实做好防汛工作……今天的上海市政府常务会议研究了这些重要事项
  • 上海护师邢红获第50届南丁格尔奖,她为何能摘得护理界最高荣誉
  • 澎湃思想周报|欧洲胜利日之思;教育监控与学生隐私权争议
  • “影像上海”中的自媒体影像特展:无论何时,影像都需要空间
  • 巴西总统卢拉昨晚抵达北京