当前位置:首页 > VUE

vue依赖收集的实现

2026-02-22 18:54:56VUE

Vue 依赖收集的实现原理

Vue 的依赖收集是通过响应式系统中的 ObserverDepWatcher 三个核心类协作完成的。以下是具体实现机制:

数据劫持(Observer)

Vue 通过 Object.definePropertyProxy(Vue 3)劫持数据的访问和修改。在 Observer 类中,递归遍历对象的属性,将其转化为响应式数据:

class Observer {
  constructor(value) {
    this.value = value;
    this.walk(value);
  }
  walk(obj) {
    Object.keys(obj).forEach(key => {
      defineReactive(obj, key, obj[key]);
    });
  }
}

defineReactive 函数为每个属性创建一个 Dep 实例(依赖管理器),并在 gettersetter 中触发依赖收集和更新。

依赖管理(Dep)

Dep 类负责管理依赖(即 Watcher 实例),核心逻辑如下:

class Dep {
  constructor() {
    this.subs = []; // 存储 Watcher 实例
  }
  addSub(sub) {
    this.subs.push(sub);
  }
  depend() {
    if (Dep.target) { // Dep.target 是当前正在计算的 Watcher
      Dep.target.addDep(this);
    }
  }
  notify() {
    this.subs.forEach(sub => sub.update());
  }
}
  • 依赖收集:在 getter 中调用 dep.depend(),将当前 Watcher 添加到 subs 中。
  • 触发更新:在 setter 中调用 dep.notify(),通知所有 Watcher 执行更新。

观察者(Watcher)

Watcher 是依赖的消费者,在组件渲染、计算属性或侦听器中被创建:

class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm;
    this.getter = expOrFn; // 更新函数(如渲染函数)
    this.cb = cb;
    this.value = this.get();
  }
  get() {
    Dep.target = this; // 设置全局目标 Watcher
    const value = this.getter.call(this.vm); // 触发 getter,收集依赖
    Dep.target = null; // 重置
    return value;
  }
  update() {
    this.run();
  }
  run() {
    const value = this.get();
    if (value !== this.value) {
      this.cb.call(this.vm, value, this.value);
    }
  }
}
  • 依赖收集过程Watcher 在初始化时执行 get() 方法,触发数据的 getter,将自身(Dep.target)添加到依赖列表中。
  • 更新过程:数据变化时,Dep 通知所有 Watcher 执行 update(),重新计算或渲染。

依赖收集的触发场景

  1. 组件渲染:渲染函数执行时,访问响应式数据会触发 getter,将渲染 Watcher 作为依赖收集。
  2. 计算属性:计算属性的 Watcher 在计算时收集其依赖的数据。
  3. 侦听器watch 选项或 $watch 创建的 Watcher 会监听特定数据的变化。

关键点总结

  • 全局唯一 Watcher:通过 Dep.target 标记当前正在计算的 Watcher,确保依赖关系准确。
  • 避免重复收集Watcher 会记录已订阅的 Dep,防止重复添加。
  • 性能优化:Vue 3 使用 ProxyWeakMap 改进依赖收集效率,支持动态属性增删。

通过这种机制,Vue 实现了数据变化到视图更新的自动关联。

vue依赖收集的实现

标签: vue
分享给朋友:

相关文章

vue单页面实现登录

vue单页面实现登录

实现登录功能的基本流程 在Vue单页面应用中实现登录功能,通常需要以下几个关键步骤: 创建登录表单组件 使用Vue的模板语法创建包含用户名和密码输入框的表单,并绑定数据到组件的data属性。 &l…

vue调用接口实现退出

vue调用接口实现退出

实现Vue退出功能的步骤 在Vue中调用接口实现退出功能通常需要与后端API交互,以下是实现方法: 前端实现 创建退出方法,调用后端API接口: methods: { logout()…

vue懒加载实现难吗

vue懒加载实现难吗

vue懒加载的实现难度 Vue懒加载的实现并不复杂,核心逻辑是通过动态导入(Dynamic Imports)和路由配置或组件异步加载完成。以下是具体实现方法: 路由懒加载实现 在Vue Router…

vue实现autocomplete

vue实现autocomplete

Vue 实现 Autocomplete 功能 Vue 中实现 Autocomplete(自动完成)功能可以通过自定义组件或使用现有库完成。以下是几种常见方法: 方法一:使用 Vue 原生实现 创建…

vue实现 toast

vue实现 toast

Vue 实现 Toast 组件 在 Vue 中实现 Toast 组件可以通过多种方式完成,以下是几种常见的方法: 使用全局组件和事件总线 创建一个全局的 Toast 组件,并通过事件总线或 Vue…

vue实现数组

vue实现数组

Vue 实现数组操作的方法 在 Vue 中,数组的操作需要特别注意响应式的问题。Vue 提供了一些方法来确保数组的变动能够触发视图更新。 响应式数组方法 Vue 对以下数组方法进行了封装,确保它们能…