当前位置:首页 > VUE

vue实现依赖收集

2026-03-08 05:02:30VUE

Vue 依赖收集实现原理

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

数据劫持

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

vue实现依赖收集

// 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),负责添加依赖和通知更新。

vue实现依赖收集

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 函数实现:

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穿梭框组件实现

vue穿梭框组件实现

实现基础穿梭框组件 在Vue中实现穿梭框组件,可以使用<el-transfer>(Element UI)或手动实现。以下是手动实现的核心逻辑: <template> &l…

vue 实现列表

vue 实现列表

Vue 实现列表的方法 在 Vue 中实现列表通常使用 v-for 指令,结合数组或对象数据渲染动态列表。以下是几种常见的实现方式: 基础列表渲染 使用 v-for 指令遍历数组,渲染列表项。ite…

vue实现图片

vue实现图片

Vue 实现图片功能的方法 静态图片引入 在 Vue 项目中,可以通过 src 属性直接引入静态图片。图片通常放在 public 或 assets 目录下。 <template> &…

vue 实现单选

vue 实现单选

使用 v-model 绑定单选值 在 Vue 中,可以通过 v-model 绑定单选按钮的值。定义一个响应式数据(如 selectedOption),并将其与单选按钮的 value 属性关联。…

vue 实现excel

vue 实现excel

Vue 实现 Excel 功能 前端导出 Excel 使用 xlsx 库可以轻松实现前端 Excel 导出功能。安装依赖: npm install xlsx 导出 Excel 示例代码: impo…

vue日历实现

vue日历实现

实现基础日历布局 使用Vue的模板语法构建日历的基本HTML结构。一个典型的日历包含星期标题和日期格子,可以通过v-for循环生成。月份切换功能通过计算属性动态更新日期数组。 <templat…