track依赖收集仅在活跃副作用执行时触发,且仅对响应式对象属性访问生效;非activeeffect上下文、普通对象、未执行分支及pausetracking期间的读取均不收集依赖。

Track 依赖收集不是“一读就记”,而是有明确的触发边界:只在活跃的副作用(effect)执行过程中、对响应式对象属性的访问才会登记依赖。
必须处于 activeEffect 上下文中
只有当前存在正在运行的 effect(比如组件 render、watchEffect、computed 的 getter),读取响应式数据时才会触发 track。全局作用域或普通函数里直接 console.log(state.count),不会收集任何依赖——因为没有 activeEffect。
- 组件首次渲染时,render 函数作为 effect 执行,内部访问 state.xxx 全部被 track
- watchEffect(() => console.log(obj.name)) 中的 obj.name 会被 track
- 但 setTimeout(() => console.log(obj.name), 0) 不会触发 track,此时无 activeEffect
仅对响应式代理对象的属性访问生效
track 由 Proxy 的 get 拦截器驱动,所以只对 reactive、ref、readonly 等 Vue 创建的响应式对象起作用。普通对象、Map/Set 实例、缓存变量(如 const cache = {})即使被读取,也不会自动 track。
- reactive({ a: 1 }).a → 触发 track
- ref(2).value → 触发 track(ref 内部也是 proxy + get/set)
- const plain = { b: 3 }; plain.b → 完全不触发 track
- 需要手动调用 track(plain, TrackOpTypes.GET, 'b') 才能建立依赖
条件分支中未执行的代码不参与收集
Vue 不会预判逻辑路径,只对实际执行到的读取操作做 track。v-if、三元表达式、if 分支里没走过的语句,其内部的响应式访问不会留下依赖记录。
- effect(() => { if (flag.value) console.log(obj.x) }) —— flag 为 false 时,obj.x 不被 track
- 计算属性中 return cond ? a.value : b.value,只 track 当前分支中实际读取的 ref
- 这意味着依赖关系是动态、路径敏感的,不是静态全量扫描
暂停期间的读取被忽略
在 effect 内部调用 pauseTracking() 后,所有后续响应式读取(包括嵌套函数中的)都不会触发 track,直到 resetTracking() 恢复。这常用于深克隆、序列化等场景,避免污染依赖图。
- pauseTracking() 只影响当前 effect 的后续执行,不影响其他 effect
- resetTracking() 清空暂存的 track 栈,恢复后新读取重新开始收集
- 漏掉 resetTracking 可能导致后续依赖收集失效,需严格配对使用
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










