分析 Vue3 Effect 函数看响应式依赖收集和触发更新过程

先给一个简单的实例,分析依赖收集和更新的过程

复制代码
let obj = { name: "hefeng6500", age: 10, flag: true }

const state = reactive(obj);

effect(() => {
  app.innerHTML = state.name + state.age
})

setTimeout(() => {
  state.age = 20
}, 1000)

reactive 函数只会创建一个响应式对象,没有产生其他的什么副作用,仅在 state 对象在访问或者修改时才会触发 proxygettersetter

依赖收集

当 effect 函数在执行时

  • Vue 底层会创建一个 ReactiveEffect 实例,创建后调用该实例的 run 方法。run 方法实际就是传入 effect 的回调函数。
  • 在执行 run 方法前,将 activeEffect = this 置为 this,也就是 activeEffect 是当前创建的 ReactiveEffect 实例。接着执行 run 方法
  • 执行 run 方法时,会访问 state.namestate.age,这就会触发两次 proxy 的 getter
  • 每触发一次 getter,就会进行一次依赖收集,也就是 track(target, key)
  • track 执行时会从 targetMap 上获取当前 taget 是否存在,未存在就 targetMap.set(target, (depsMap = new Map())) 接着,在 depsMap 上寻找 key 是否存在不存在就设置 depsMap.set(key, new Map())

最后 depsMap 保存格式如下:

  • 执行 track 时,内部调用了 trackEffect,它将刚刚的 activeEffect.deps 数组上添加了 nameage 这两个 dep,并且 这两个 dep 上分别保存了 这个 activeEffect。形成了双向记忆。

触发更新

当执行 state.age = 20

  • 触发 proxy 的 setter,进而触发 trigger 函数,找出 age 对应的 dep。调用 triggerEffects(dep)
  • triggerEffects 拿到 dep 后将该 dep 上所有的 effect 拿出来,调用它的 scheduler(其实就是 run 方法,也就是 effect 传入的回调函数)
相关推荐
IccBoY16 分钟前
NVM超详细全解教程:解决Node版本冲突(Win/Mac/Linux安装+使用+踩坑合集)
前端·node.js
wuhen_n19 分钟前
前端工程师进阶提示词工程实战
前端·langchain·ai编程
GISer_Jing30 分钟前
Claude Code MCP Server 集成全解析
前端·人工智能·ai·架构
蚰蜒螟31 分钟前
走进 Linux 内核:从 touch 命令到磁盘 inode 的完整旅程
java·linux·前端
因_崔斯汀34 分钟前
用 AI 编程助手从零生成 3D 智慧校园数据大屏 —— Claude Code 实战全记录
前端
前端Hardy35 分钟前
CSS 动画真的比 JS 快?Josh Comeau 做了组实验,结果跟直觉不一样
前端·javascript·后端
用户8417948145636 分钟前
vxe-gantt 甘特图在 Nuxt 中的集成与使用
vue.js
自进化Agent智能体41 分钟前
MCP与Hooks:让AI Agent安全连接一切的治理框架
前端
明天一点43 分钟前
Cloudflare 通知转发钉钉机器人
前端·后端
前端Hardy43 分钟前
前端日历组件,要变天了?Schedule-X v4.6 彻底杀疯了
前端·javascript·后端