当前位置:首页 > 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 Router 实现基础导航 在 Vue 项目中,可以通过 Vue Router 实现导航栏的路由切换。创建一个导航栏组件,并在其中使用 <router-li…

vue懒加载实现难吗

vue懒加载实现难吗

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

vue 实现菜单

vue 实现菜单

Vue 实现菜单的方法 使用 Vue 实现菜单可以通过多种方式,以下是几种常见的方法: 使用 Vue Router 实现动态路由菜单 通过 Vue Router 可以动态生成菜单,根据路由配置自动渲…

vue实现节流

vue实现节流

vue实现节流的方法 在Vue中实现节流(throttle)功能,通常用于限制高频事件的触发频率,例如滚动、输入或按钮点击。以下是几种常见的实现方式: 使用Lodash的throttle函数 安装L…

vue 实现拖动

vue 实现拖动

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

vue实现接口

vue实现接口

在 Vue 中实现接口请求 Vue 本身不直接提供 HTTP 请求功能,通常需要借助第三方库如 axios 或 fetch 来实现接口请求。以下是几种常见方法: 使用 axios 发送请求 安装 a…