当前位置:首页 > VUE

vue响应式的实现

2026-02-24 06:27:55VUE

Vue 响应式原理

Vue 的响应式系统基于 JavaScript 的 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)实现。核心是通过数据劫持结合发布-订阅模式,自动追踪依赖并在数据变化时触发更新。

Vue 2.x 实现方式

数据劫持 使用 Object.defineProperty 递归地将对象的属性转换为 getter/setter,在访问或修改数据时触发依赖收集和更新。

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log(`读取 ${key}: ${val}`);
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        console.log(`设置 ${key}: ${newVal}`);
        val = newVal;
      }
    }
  });
}

依赖收集 每个响应式属性关联一个 Dep 实例,用于存储依赖(即 Watcher 实例)。在 getter 中收集依赖,在 setter 中通知更新。

vue响应式的实现

class Dep {
  constructor() {
    this.subscribers = [];
  }
  depend() {
    if (target && !this.subscribers.includes(target)) {
      this.subscribers.push(target);
    }
  }
  notify() {
    this.subscribers.forEach(sub => sub());
  }
}

Watcher Watcher 代表一个依赖,在初始化时触发 getter 以收集依赖,数据变化时执行回调。

let target = null;
function watcher(fn) {
  target = fn;
  target();
  target = null;
}

Vue 3.x 实现方式

Proxy 代理 Vue 3 使用 Proxy 替代 Object.defineProperty,能直接监听对象和数组的变化,无需递归遍历。

vue响应式的实现

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key);
      return target[key];
    },
    set(target, key, value) {
      target[key] = value;
      trigger(target, key);
    }
  });
}

依赖跟踪与触发 通过 tracktrigger 函数管理依赖关系,原理与 Vue 2.x 类似,但实现更简洁。

const targetMap = new WeakMap();
function track(target, key) {
  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;
  depsMap.get(key).forEach(effect => effect());
}

响应式系统的局限性

对象新增属性 Vue 2.x 无法检测对象属性的添加或删除,需使用 Vue.setVue.delete。Vue 3.x 通过 Proxy 解决了这一问题。

数组变化 Vue 2.x 通过重写数组方法(如 pushpop)实现响应式,直接通过索引修改或修改长度不会触发更新。Vue 3.x 的 Proxy 支持对数组的全面监听。

总结

Vue 的响应式系统通过数据劫持和依赖管理实现自动更新。Vue 2.x 依赖 Object.defineProperty,需处理一些边界情况;Vue 3.x 改用 Proxy,提供了更完善的响应式支持。

标签: vue
分享给朋友:

相关文章

vue中如何实现循环

vue中如何实现循环

在 Vue 中实现循环 Vue 提供了 v-for 指令用于实现循环渲染列表数据。v-for 可以遍历数组、对象或数字范围,生成动态的 DOM 元素。 遍历数组 使用 v-for 遍历数组时,语法为…

vue交互实现

vue交互实现

Vue 交互实现方法 Vue.js 提供了多种方式实现用户交互,包括事件处理、表单绑定、动态渲染等。以下是常见的交互实现方法: 事件处理 通过 v-on 或 @ 指令绑定事件,触发方法或直接执行表…

vue实现批量

vue实现批量

Vue 实现批量操作的方法 在 Vue 中实现批量操作通常涉及选择多个项目并执行统一处理,例如批量删除、批量更新等。以下是几种常见实现方式: 表格多选批量操作 使用 el-table 配合复选框实现…

vue 实现拖动

vue 实现拖动

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

vue实现粘贴

vue实现粘贴

Vue 实现粘贴功能的方法 在 Vue 中实现粘贴功能通常涉及监听粘贴事件并处理剪贴板数据。以下是几种常见的实现方式: 监听原生粘贴事件 通过 @paste 指令或原生 addEventListe…

vue多选实现

vue多选实现

Vue 多选实现方法 基础实现(v-model + multiple) 在 Vue 中实现多选可以通过 <select> 元素的 multiple 属性结合 v-model 完成。v-mo…