当前位置:首页 > VUE

vue实现依赖收集

2026-03-08 05:02:30VUE

Vue 依赖收集实现原理

Vue 的依赖收集是通过响应式系统实现的,核心机制基于 Object.defineProperty(Vue 2)或 Proxy(Vue 3)。以下是关键实现步骤:

数据劫持

通过 Object.definePropertyProxy 拦截数据的读取和修改操作。当组件渲染时访问数据属性,触发 getter 收集依赖;当数据变更时,触发 setter 通知更新。

// Vue 2 实现示例
function defineReactive(obj, key) {
  const dep = new Dep(); // 每个属性对应一个 Dep 实例
  let val = obj[key];
  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) { // 当前正在计算的 Watcher
        dep.depend();   // 收集依赖
      }
      return val;
    },
    set(newVal) {
      if (val === newVal) return;
      val = newVal;
      dep.notify(); // 通知更新
    }
  });
}

Dep 类

Dep 是依赖管理器,维护一个订阅者列表(subs),负责添加依赖和通知更新。

class Dep {
  constructor() {
    this.subs = [];
  }
  depend() {
    if (Dep.target) {
      this.subs.push(Dep.target);
    }
  }
  notify() {
    this.subs.forEach(watcher => watcher.update());
  }
}
Dep.target = null; // 静态属性,指向当前 Watcher

Watcher 类

Watcher 是观察者,代表一个依赖。在组件渲染或计算属性求值时创建,通过 get 方法触发数据的 getter 以收集依赖。

class Watcher {
  constructor(vm, expOrFn) {
    this.vm = vm;
    this.getter = parsePath(expOrFn);
    this.value = this.get();
  }
  get() {
    Dep.target = this; // 设置当前 Watcher
    const value = this.getter.call(this.vm, this.vm);
    Dep.target = null; // 收集完成后重置
    return value;
  }
  update() {
    this.get(); // 重新求值并触发更新
  }
}

依赖收集流程

  1. 组件初始化:渲染组件时创建 Watcher,执行 render 函数访问数据。
  2. 触发 getter:数据属性的 getter 被调用,当前 WatcherDep.target)被添加到 Dep 的订阅列表。
  3. 依赖建立:数据属性与 Watcher 建立关联,后续数据变化时通过 setter 触发 Dep.notify()
  4. 派发更新notify 调用所有关联 Watcherupdate 方法,重新渲染或计算。

Vue 3 的改进

Vue 3 使用 Proxy 替代 Object.defineProperty,解决了数组和新增属性的监听问题。依赖收集逻辑类似,但通过 tracktrigger 函数实现:

vue实现依赖收集

const proxy = new Proxy(obj, {
  get(target, key) {
    track(target, key); // 替代 dep.depend()
    return Reflect.get(target, key);
  },
  set(target, key, value) {
    Reflect.set(target, key, value);
    trigger(target, key); // 替代 dep.notify()
  }
});

关键点总结

  • 响应式数据:通过劫持数据访问实现自动依赖跟踪。
  • 发布-订阅模式Dep 管理依赖,Watcher 作为订阅者。
  • 动态更新:数据变化时精确通知相关依赖,避免不必要的渲染。

标签: vue
分享给朋友:

相关文章

vue实现iframe

vue实现iframe

Vue 中实现 iframe 的方法 在 Vue 项目中,可以通过多种方式实现 iframe 的嵌入。以下是几种常见的方法: 使用原生 HTML iframe 标签 直接在 Vue 组件的模板中使用…

vue 实现递归

vue 实现递归

Vue 实现递归组件的方法 在 Vue 中实现递归组件通常用于处理树形结构数据,例如菜单、评论列表或文件目录。以下是实现递归组件的关键步骤: 定义递归组件 递归组件需要设置 name 属性,以便在模…

vue实现menu

vue实现menu

Vue 实现 Menu 的方法 使用 Element UI 的 Menu 组件 Element UI 提供了现成的 Menu 组件,适合快速实现导航菜单。安装 Element UI 后,可以直接使用…

vue递归实现

vue递归实现

vue递归实现方法 在Vue中实现递归组件通常用于树形结构、嵌套菜单等场景。以下是具体实现方式: 使用组件name属性递归 定义一个组件时,通过name属性让组件可以在自身模板中调用自己: <…

vue实现checkbox

vue实现checkbox

Vue 实现 Checkbox 在 Vue 中实现 Checkbox 可以通过原生 HTML 的 <input type="checkbox"> 或使用 Vue 的 v-model 指令绑…

vue实现spa

vue实现spa

Vue 实现 SPA(单页应用)的步骤 创建 Vue 项目 使用 Vue CLI 快速初始化一个 Vue 项目,确保安装了 Vue Router 作为路由管理工具。运行以下命令创建项目: vue c…