请描述 Vue 响应式系统中依赖收集的过程,包括各个相关的核心模块及其协作方式。
考察说明
考查对 Vue 响应式原理中依赖收集机制的理解,包括核心模块和流程。
回答思路
- 【回答框架 1】依赖收集发生在 Vue 2 的 Observer 和 Watcher 模块中,核心是每个响应式属性通过 Object.defineProperty 转为 getter/setter。组件渲染时读取数据触发 getter,getter 调用 Dep.depend() 将当前 Watcher(如渲染 Watcher)收集进该属性的 Dep 中。
- 【回答框架 2】Dep 是依赖管理器,每个属性对应一个 Dep 实例,内部存储一个 Watcher 列表。Watcher 在构造时会把自身设为 Dep.target,然后读取数据触发 getter 完成依赖收集,收集完成后恢复之前的 Dep.target。
- 【回答框架 3】当属性被修改时,setter 触发 Dep.notify(),通知列表中的 Watcher 执行 update,进而触发视图更新。组件更新时可能重新读取数据,新增的依赖会被收集,移除的依赖不会被主动清理,这可能导致额外开销。
- 【回答框架 4】Vue 3 改为基于 Proxy 的依赖收集,使用 WeakMap 存储对象与属性对应的 Dep,同样在访问属性时收集。Vue 3 还引入了 effect 和 track/trigger 机制,依赖收集核心思路相同,但实现更精细并支持依赖清理。
- 【关键点 1】依赖收集是在数据读取时通过 getter 将当前 Watcher 记录到 Dep 中。
- 【关键点 2】Watcher 通过设置 Dep.target 并在读取时调用 Dep.depend 完成收集。
- 【关键点 3】数据变化时 setter 触发 Dep.notify 通知 Watcher 更新。
- 【关键点 4】Vue 3 使用 Proxy 和 WeakMap 存储依赖,核心原理类似。
- 【易错点 1】依赖收集只跟踪依赖,不保证业务幂等,业务幂等等特性需要额外机制支持。
- 【易错点 2】Vue 2 的依赖收集粒度较粗,组件更新时可能重新收集依赖,需要理解其更新逻辑。