当前位置:首页 > 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单页面应用中实现登录功能,通常需要以下几个关键步骤: 创建登录表单组件 使用Vue的模板语法创建包含用户名和密码输入框的表单,并绑定数据到组件的data属性。 <…

vue实现安全免登录

vue实现安全免登录

Vue 实现安全免登录的方案 免登录功能通常通过持久化认证状态(如 Token)实现,但需兼顾安全性。以下是基于 Vue 的常见实现方案: 基于 Token 的免登录 登录成功后存储 Token…

实现vue组件

实现vue组件

Vue 组件的基本实现 Vue 组件是 Vue.js 的核心特性之一,允许将 UI 拆分为独立、可复用的模块。以下是实现 Vue 组件的几种方式: 单文件组件 (SFC) 使用 .vue 文件格式,…

vue实现遮罩

vue实现遮罩

Vue 实现遮罩层的方法 在 Vue 中实现遮罩层可以通过多种方式完成,以下是几种常见的方法: 方法一:使用 v-show 或 v-if 控制显示 通过 Vue 的指令动态控制遮罩层的显示与隐藏。…

vue原理实现

vue原理实现

Vue 原理实现的核心机制 Vue.js 的核心原理基于响应式系统、虚拟 DOM 和模板编译。以下是其核心实现机制的分解: 响应式系统 Vue 使用 Object.defineProperty(Vu…

vue实现portal

vue实现portal

Vue 实现 Portal 功能 Portal 是一种将子节点渲染到父组件 DOM 层级之外的 DOM 节点的技术,常用于实现模态框、弹出层等需要脱离当前组件层级的场景。Vue 可以通过多种方式实现…