vue响应式系统不使用双向链表,而是基于单向映射(target→key→set)实现依赖追踪与触发更新;track是内部getter中自动执行的逻辑,trigger通过哈希查找并执行对应effect集合。

Vue.js 的响应式系统里没有叫 “Track 追踪函数” 的独立 API,也没有显式使用双向链表来实现依赖收集与触发更新。这是对底层机制的一种常见误解或术语混淆。Vue 3 的响应式核心(基于 Proxy)和 Vue 2(基于 Object.defineProperty)都采用“依赖追踪 + 订阅者模式”的变体,其数据结构本质是**单向映射关系(target → key → Set
依赖是如何被“追踪”(track)的?
所谓 track,并非一个用户可调用的函数,而是响应式系统内部在 getter 中自动执行的逻辑:
- 当访问响应式对象的某个属性(如 state.count)时,会触发 Proxy 的 get 拦截器
- 此时若存在正在执行的副作用函数(如 setup 中的计算属性、watch 或渲染函数),系统会将该 effect 记录到该属性对应的依赖集合中
- 这个过程由 track(target, type, key) 内部函数完成,它维护的是 key → Set
的映射
触发更新(trigger)时发生了什么?
当设置属性值(set)时,系统执行 trigger,查找并执行所有订阅了该 key 的 effect:
- 根据 target 和 key,从缓存中取出对应的 effect 集合
- 依次运行这些 effect(可能先做防重复调度优化,比如加队列、去重)
- 整个过程不涉及 prev/next 指针,也不需要双向遍历 —— 是典型的哈希查找 + 集合迭代
为什么不是双向链表?
双向链表常用于需要高效插入/删除且频繁前后遍历的场景(如浏览器历史、LRU 缓存)。但 Vue 的依赖管理需求不同:
- 依赖注册是“一次写入、多次读取”,更看重 O(1) 查找效率,哈希表(Map/Set)天然胜任
- effect 执行顺序不依赖链式关系,而是靠调度器(scheduler)统一控制(如 queueJob 做异步去重)
- 源码中 dep 是一个 Set,targetMap 是 Map
,无任何链表节点字段
容易混淆的来源
部分文章将“effect 之间可能存在嵌套执行”或“cleanup 时需解除当前 effect 对旧依赖的订阅”脑补成链表结构;也有把 React 的 fiber 树双链表(parent/child/sibling)误迁移到 Vue 解释中。实际上,Vue 的 effect 清理靠的是在重新 track 前自动调用 cleanup(effect),遍历它自己记录的 deps 数组并从各 dep 的 Set 中 delete 自身 —— 这仍是基于集合操作,不是链表解绑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











