当前位置:首页 > VUE

vue 响应式实现

2026-03-28 19:32:07VUE

Vue 响应式原理

Vue 的响应式系统通过数据劫持结合发布-订阅模式实现。核心是利用 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}`);
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      console.log(`更新 ${key}`);
      val = newVal;
    }
  });
}

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

class Dep {
  constructor() {
    this.subs = [];
  }
  addSub(sub) {
    this.subs.push(sub);
  }
  notify() {
    this.subs.forEach(sub => sub.update());
  }
}

function defineReactive(obj, key, val) {
  const dep = new Dep();
  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) dep.addSub(Dep.target);
      return val;
    },
    set(newVal) {
      val = newVal;
      dep.notify();
    }
  });
}

Vue 3.x 实现方式

Proxy 代理 Vue 3 使用 Proxy 监听整个对象,无需递归遍历:

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); // 触发更新
      return true;
    }
  });
}

依赖管理 通过 WeakMapMap 建立响应式对象与依赖的映射关系:

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;
  const effects = depsMap.get(key);
  effects && effects.forEach(effect => effect());
}

对比差异

  1. 性能优化

    • Proxy 直接代理整个对象,无需递归初始化。
    • Object.defineProperty 需要遍历每个属性,对嵌套对象需递归处理。
  2. 数组监听

    • Proxy 可监听数组索引变化和 push/pop 等方法。
    • Object.defineProperty 需重写数组方法实现响应式。
  3. 新数据类型支持

    vue 响应式实现

    • Proxy 支持 MapSet 等数据结构。
    • Object.defineProperty 仅适用于纯对象。

注意事项

  • 避免直接替换响应式对象:重新赋值会丢失响应性,应使用 Vue.set 或更新嵌套属性。
  • 异步更新队列:Vue 将 DOM 更新合并为异步任务,减少重复渲染。

标签: vue
分享给朋友:

相关文章

vue实现多选div

vue实现多选div

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

vue交互实现

vue交互实现

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

vue菜单实现

vue菜单实现

Vue 菜单实现方法 使用 Element UI 的菜单组件 Element UI 提供了现成的菜单组件,适合快速实现导航菜单。安装 Element UI 后,可以直接使用 el-menu 相关组件。…

vue分类实现

vue分类实现

Vue分类实现方法 在Vue中实现分类功能通常涉及数据分组、动态渲染和交互逻辑。以下是几种常见的实现方式: 基于计算属性的分类 通过计算属性对原始数据进行分组处理,适合静态或少量数据分类: com…

vue 实现筛选

vue 实现筛选

实现筛选功能的基本方法 在Vue中实现筛选功能通常涉及以下几个核心步骤: 数据绑定与筛选逻辑 使用v-model绑定筛选条件到Vue实例的数据属性,结合计算属性实现动态筛选: data() {…

vue实现addclass

vue实现addclass

Vue 实现动态添加 class 的方法 在 Vue 中动态添加 class 可以通过多种方式实现,以下是常见的几种方法: 使用对象语法 通过绑定一个对象到 :class,可以动态切换 class…