根据这张图进行总结
在组件实例初始化阶段,通过 observe()
方法对 data
对象进行递归遍历。在这个过程中,Vue 使用 Object.defineProperty()
为data
中的每个属性定义 getter
和 setter
来拦截对象属性的“读取“操作和“写入”操作。
Vue 的依赖追踪是通过 Watcher
和 Dep
协同完成的。其中,每个响应式属性背后都对应一个 Dep
对象,负责收集依赖(即 Watcher)并在数据变更时通知更新。
在组件挂载阶段,Vue 会自动创建一个渲染 Watcher。该 Watcher 会执行组件的 render 函数,并在执行过程中读取模板中所用到的响应式数据。这些数据的读取会触发它们的 getter
,从而使当前正在运行的 Watcher(即渲染 Watcher)被 Dep 收集为依赖。
这个过程叫做 依赖收集(Dependency Collection)。大概的过程是:
- Watcher 在评估表达式(执行它所监听的函数或访问的数据)或渲染函数之前,把自身赋值给 Dep.target;
- 当访问响应式属性时,触发其 getter;
- 在 getter 中调用 dep.depend(),把当前 Dep.target(Watcher)添加到依赖列表中;
- 当属性变化时,setter 被触发,Dep 会通过 dep.notify() 通知所有依赖该属性的 Watcher 执行更新逻辑。
Vue 中的 Watcher 有三种类型:
- 渲染 Watcher:用于渲染视图;
- 计算属性 Watcher:用于计算属性的缓存与依赖追踪;
- 侦听器 Watcher:用于执行 watch 回调函数。
总结:
在 Vue 的响应式系统中,Observer
负责劫持数据,Dep
负责依赖管理,而 Watcher
是响应式更新的执行者。组件挂载时创建渲染 Watcher
,读取数据触发 getter
,完成依赖收集。数据变更时,依赖该数据的 Watcher 会被通知更新,从而驱动视图响应式变化。
组件 | 关键词 | 作用 |
---|---|---|
Observer | 劫持 | 将数据变成响应式 |
Dep | 收集依赖 | 保存 Watcher 列表 |
Watcher | 更新逻辑 | 数据变了就执行 |
Compile | 模板解析 | 把模板变成 Watcher |
View | 自动更新 | Watcher 通知它变化 |