vue依赖收集与触发是observer、dep、watcher协同完成的“登记—广播”机制:observer监控数据,dep管理订阅者列表,watcher代表响应任务;依赖在读取时收集,更新由setter精准广播。

Vue 的依赖收集与触发,不是抽象概念,而是有明确角色分工、按步骤执行的一套联动机制。它像一个“登记—广播”系统:谁看了什么数据,就记在对应数据的小本子上;等数据一改,立刻翻出小本子,挨个通知。
三个核心角色各司其职
整个过程靠 Observer、Dep 和 Watcher 协同完成,缺一不可:
-
Observer:负责给数据“装监控”。Vue 2 用
Object.defineProperty给每个属性加 getter/setter;Vue 3 用Proxy直接代理整个对象,能监听新增属性、数组索引、Map/Set 等。 - Dep:每个响应式属性背后都有一个 Dep 实例,本质是一个“订阅者列表”。它不判断逻辑,只干两件事——把 Watcher 加进来(收集),等 setter 触发时把所有 Watcher 叫醒(通知)。
-
Watcher:代表一个需要响应数据变化的任务。组件渲染函数、
computed的 getter、watch的回调,背后都是 Watcher。它在执行过程中读取数据,从而触发 getter,完成自身注册。
依赖收集发生在“读取那一刻”
收集不是预先扫描,也不是写数据时发生,而是在你真正访问数据的瞬间触发:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 模板里写
{{ count }}→ 渲染时读this.count→ 触发count的 getter → 当前组件 Watcher 被加入count对应的 Dep。 -
computed: { fullName() { return this.firstName + this.lastName } }→ 首次求值时,firstName和lastName的 getter 都被调用 → 各自 Dep 分别记下这个 computed Watcher。 -
watch: { age() { ... } }→ 内部新建 Watcher 去读this.age→ 完成对age的依赖登记。
触发更新是 setter 带来的“精准广播”
当你改数据,比如 this.message = 'hello',setter 被触发,流程如下:
- 找到
message属性对应的 Dep; - 遍历 Dep 中所有已登记的 Watcher(可能是多个组件、计算属性、watch 回调);
- 逐个调用它们的
update()方法; - 渲染 Watcher 会标记组件为“待更新”,最终通过异步队列批量刷新视图。
Vue 3 的 track / trigger 更清晰解耦
Vue 3 把依赖逻辑抽离为独立函数,结构更直观:
-
track(target, key):访问属性时调用,从全局targetMap中取出该对象的depsMap,再取出key对应的dep,最后把当前活跃的 effect(即 Watcher)加进去; -
trigger(target, key):修改属性时调用,同样定位到dep,然后遍历并执行所有订阅者的更新逻辑; -
targetMap → depsMap → dep这三层映射,确保不同对象、不同属性的依赖互不干扰,也支持嵌套对象和动态属性。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










