Vue.js响应式系统中track是内部函数,仅在Proxy get拦截器中自动执行,用于建立数据属性与活跃effect的依赖关系,其底层结构为WeakMap→Map→Set三层嵌套映射。

Vue.js 响应式系统中没有独立暴露的 track 函数供开发者直接调用,它是一个内部逻辑函数,只在 Proxy 的 get 拦截器中被自动执行。它的作用不是“监听用户操作”,而是建立数据属性与当前活跃副作用(effect)之间的订阅关系。
track 的核心职责:登记依赖
当访问一个响应式对象的属性(如 state.count)时,track 会做三件事:
- 确认当前是否存在正在执行的副作用函数(即
activeEffect不为 null); - 根据目标对象
target和属性键key,从全局targetMap中获取或创建对应的依赖映射depsMap(类型为Map); - 再从
depsMap中取出该key对应的依赖集合dep(类型为Set),并将activeEffect加入其中。
整个过程不涉及 DOM 事件、用户点击或埋点行为,纯粹是数据读取时的依赖登记动作。
底层数据结构:WeakMap + Map + Set
依赖关系图由三层嵌套结构维护:
立即学习“前端免费学习笔记(深入)”;
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
-
targetMap: WeakMap<target, depsMap>—— 键是响应式对象,值是它的属性依赖映射; -
depsMap: Map<key, dep>—— 键是属性名(字符串或 Symbol),值是该属性的依赖集合; -
dep: Set<effect>—— 存储所有依赖该属性的副作用函数。
使用 WeakMap 可避免内存泄漏:当响应式对象被垃圾回收时,其对应条目可被自动清理。
track 何时生效?关键限制条件
并不是每次读取都会触发依赖收集。只有满足以下全部条件时,track 才真正记录依赖:
- 读取发生在响应式对象(
reactive或ref)上; - 当前有激活的 effect 正在执行(例如组件 render、
watchEffect、computed); - 该属性此前未被该 effect 收集过(
dep中尚无此effect)。
例如:console.log(state.count) 在全局作用域执行,因无 active effect,不会收集依赖;v-if="false" 内部的读取也不会被 track。
customRef 中的手动 track 与 trigger
customRef 是少数允许开发者显式调用 track 和 trigger 的 API:
-
get()中必须调用track(),否则后续trigger()无法通知任何 effect; -
set()中更新闭包变量后,必须调用trigger(),否则视图不会刷新; - 这两个函数由 Vue 注入,不是全局方法,也不接受参数,仅在
customRef工厂函数内可用。
这说明 track 本质是“注册读取意图”,trigger 是“宣告变更事实”——二者构成响应式闭环的最小契约。

















