当前位置:首页 > 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 中通知更新:

vue 响应式实现

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 建立响应式对象与依赖的映射关系:

vue 响应式实现

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. 新数据类型支持

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

注意事项

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

标签: vue
分享给朋友:

相关文章

vue实现tab换行

vue实现tab换行

Vue实现Tab切换的常见方法 使用Vue实现Tab切换功能可以通过多种方式完成,以下是几种常见的方法: 动态组件结合v-if或v-show 通过v-if或v-show控制不同Tab内容的显示与隐…

vue实现用户信息删除

vue实现用户信息删除

Vue 实现用户信息删除功能 在 Vue 中实现用户信息删除功能通常涉及前端界面交互和后端 API 调用。以下是实现步骤: 前端界面设计 创建删除按钮或操作项,通常使用 @click 事件触发删除操…

vue实现store

vue实现store

Vue 实现 Store 在 Vue 中,可以通过 Vuex 或 Pinia 实现全局状态管理(Store)。以下是两种主流方案的实现方法。 使用 Vuex 实现 Store Vuex 是 Vue…

vue el 实现

vue el 实现

Vue 中使用 Element UI (el) 的实现方法 Element UI 是一个基于 Vue 的组件库,提供丰富的 UI 组件,常用于快速构建企业级中后台产品。以下介绍 Vue 项目中集成和使…

vue实现选择

vue实现选择

Vue 实现选择功能的方法 在 Vue 中实现选择功能可以通过多种方式完成,以下介绍几种常见的实现方法。 使用 v-model 绑定单选 通过 v-model 可以轻松实现单选功能。以下是一个简单的…

vue实现网站

vue实现网站

Vue 实现网站的基本步骤 Vue.js 是一个渐进式 JavaScript 框架,适合构建现代化的单页应用(SPA)或动态网站。以下是使用 Vue 实现网站的基本方法。 初始化 Vue 项目 使用…