当前位置:首页 > VUE

vue依赖收集的实现

2026-01-22 03:51:53VUE

Vue 依赖收集的实现原理

Vue 的依赖收集是通过响应式系统实现的,核心在于 ObserverDepWatcher 三者的协作。

响应式数据初始化

通过 Object.definePropertyProxy(Vue 3)劫持数据对象的属性访问。在 getter 中触发依赖收集,在 setter 中触发更新通知。

function defineReactive(obj, key, val) {
  const dep = new Dep();
  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) {
        dep.depend(); // 收集依赖
      }
      return val;
    },
    set(newVal) {
      if (val === newVal) return;
      val = newVal;
      dep.notify(); // 触发更新
    }
  });
}

Dep 类管理依赖

Dep 是依赖管理器,每个响应式属性对应一个 Dep 实例,用于存储所有依赖该属性的 Watcher

class Dep {
  constructor() {
    this.subs = []; // 存储 Watcher 实例
  }
  depend() {
    if (Dep.target) {
      this.subs.push(Dep.target); // 添加 Watcher
    }
  }
  notify() {
    this.subs.forEach(watcher => watcher.update()); // 通知更新
  }
}
Dep.target = null; // 全局唯一 Watcher 标记

Watcher 类触发依赖

Watcher 是观察者,在组件渲染或计算属性求值时被创建。它会将自身赋值给 Dep.target,触发属性的 getter 从而完成依赖收集。

class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm;
    this.getter = parsePath(expOrFn);
    this.cb = cb;
    this.value = this.get();
  }
  get() {
    Dep.target = this; // 标记当前 Watcher
    const value = this.getter.call(this.vm, 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);
    }
  }
}

依赖收集流程

  1. 组件初始化时创建 Watcher,触发 get 方法。
  2. Dep.target 被设置为当前 Watcher
  3. 访问响应式数据时触发 getter,调用 dep.depend()Watcher 存入 subs
  4. 数据变化时触发 setter,调用 dep.notify() 通知所有 Watcher 更新。

Vue 3 的优化

Vue 3 改用 Proxy 实现响应式,依赖收集逻辑类似但更高效:

vue依赖收集的实现

  • 通过 track 函数收集依赖(对应 depend)。
  • 通过 trigger 函数触发更新(对应 notify)。
  • 使用 WeakMapSet 存储依赖关系,避免内存泄漏。

标签: vue
分享给朋友:

相关文章

vue实现用户信息表

vue实现用户信息表

Vue 实现用户信息表的方法 使用 Vue CLI 创建项目 安装 Vue CLI 并初始化项目: npm install -g @vue/cli vue create user-info-tabl…

vue 实现拖动

vue 实现拖动

Vue 实现拖动的几种方法 在Vue中实现拖动功能可以通过多种方式,包括原生HTML5的拖放API、第三方库如vuedraggable等。以下是几种常见的实现方法: 使用HTML5拖放API HTM…

vue 实现href

vue 实现href

Vue 实现 href 的方法 在 Vue 中实现 href 功能可以通过多种方式,具体取决于需求场景。以下是几种常见的方法: 使用 <a> 标签 直接使用 HTML 的 <a&g…

vue 实现树状

vue 实现树状

Vue 实现树状结构的方法 递归组件实现树状结构 递归组件是 Vue 中实现树状结构的常见方法。通过组件自身调用自身,可以轻松构建多层级树状结构。 <template> <ul…

vue实现api

vue实现api

Vue 实现 API 调用 在 Vue 中调用 API 通常涉及使用 axios 或 fetch 发送 HTTP 请求,并结合 Vue 的响应式特性管理数据。以下是常见的实现方式: 安装 axios…

vue实现绘图

vue实现绘图

Vue 实现绘图的方法 在 Vue 中实现绘图功能,可以通过多种方式实现,包括使用原生 HTML5 Canvas、第三方库(如 Fabric.js、Konva.js)或 SVG。以下是几种常见的实现方…