当前位置:首页 > VUE

vue数据响应式实现

2026-02-23 13:16:15VUE

Vue 数据响应式实现原理

Vue 的数据响应式是通过 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)实现的,核心是依赖收集和派发更新。

Vue 2.x 的实现

数据劫持 通过 Object.defineProperty 对对象的属性进行劫持,在 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 (newVal === val) return;
      val = newVal;
      dep.notify(); // 触发更新
    }
  });
}

依赖收集 每个响应式属性都有一个 Dep 实例,用于管理依赖(即 Watcher 实例)。当数据被访问时,当前 Watcher 会被添加到 Dep 中。

vue数据响应式实现

class Dep {
  constructor() {
    this.subs = [];
  }

  depend() {
    if (Dep.target) {
      this.subs.push(Dep.target);
    }
  }

  notify() {
    this.subs.forEach(sub => sub.update());
  }
}

Watcher Watcher 是观察者,负责执行更新操作(如渲染视图)。在初始化时,会将当前 Watcher 设置为 Dep.target,触发 getter 收集依赖。

class Watcher {
  constructor(vm, key, cb) {
    this.vm = vm;
    this.key = key;
    this.cb = cb;
    Dep.target = this;
    this.value = vm[key]; // 触发 getter,收集依赖
    Dep.target = null;
  }

  update() {
    this.value = this.vm[this.key];
    this.cb(this.value);
  }
}

Vue 3.x 的实现

Vue 3.x 使用 Proxy 替代 Object.defineProperty,解决了 Vue 2.x 中无法检测数组和对象新增属性的问题。

vue数据响应式实现

Proxy 数据劫持 通过 Proxy 拦截对象的操作,包括属性访问、赋值、删除等。

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      track(target, key); // 收集依赖
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(target, key); // 触发更新
      return true;
    }
  });
}

依赖管理 Vue 3.x 使用 effect 替代 Watcher,通过 tracktrigger 管理依赖。

const targetMap = new WeakMap();

function track(target, key) {
  if (!activeEffect) return;
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()));
  }
  let dep = depsMap.get(key);
  if (!dep) {
    depsMap.set(key, (dep = new Set()));
  }
  dep.add(activeEffect);
}

function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;
  const dep = depsMap.get(key);
  if (dep) {
    dep.forEach(effect => effect());
  }
}

let activeEffect;

function effect(fn) {
  activeEffect = fn;
  fn();
  activeEffect = null;
}

总结

  • Vue 2.x:通过 Object.defineProperty 劫持数据,结合 DepWatcher 实现依赖收集和派发更新。
  • Vue 3.x:通过 Proxy 实现更全面的数据劫持,使用 effecttracktrigger 管理依赖,性能更好且支持更多操作。

标签: 数据vue
分享给朋友:

相关文章

vue实现多选div

vue实现多选div

实现多选 DIV 的基本思路 在 Vue 中实现多选 DIV 功能,可以通过以下方法实现。主要思路是利用 v-model 绑定选中状态,结合 CSS 类名动态切换样式。 数据准备与模板结构 定义一个…

vue实现前端

vue实现前端

Vue 实现前端的核心方法与步骤 安装 Vue 项目 使用 Vue CLI 或 Vite 创建项目。Vue CLI 是传统构建工具,Vite 是新一代轻量级工具。 npm init vue@la…

vue toast实现

vue toast实现

Vue Toast 实现方法 使用第三方库(推荐) 安装 vue-toastification 库,这是一个功能丰富且轻量级的 Vue Toast 插件。 npm install vue-toast…

vue实现加载

vue实现加载

Vue 实现加载功能的方法 使用 v-if 或 v-show 控制加载状态 通过数据绑定控制加载动画的显示与隐藏。v-if 会完全移除 DOM 元素,v-show 只是切换 display 属性。…

vue实现精准查询

vue实现精准查询

实现精准查询的方法 在Vue中实现精准查询通常需要结合输入框、数据处理和筛选逻辑。以下是几种常见的方法: 使用计算属性进行筛选 计算属性适合对数据进行实时筛选,响应输入框的变化: <tem…

vue  怎么实现双击

vue 怎么实现双击

实现双击事件的方法 在 Vue 中实现双击事件可以通过 @dblclick 指令或自定义逻辑实现。以下是两种常见方法: 使用 @dblclick 指令 Vue 提供了原生 @dblclick 指令,…