Vue数据响应式原理解析

Vue 的数据响应式原理是其核心特性之一,它实现了数据变化自动驱动视图更新。Vue 2.x 和 Vue 3.x 的实现方式不同,下面分别详解:


Vue 2.x 的响应式原理(基于 Object.defineProperty)

核心步骤:

  1. 数据劫持(Observer):
    -遍历 data 中的每个属性,用 Object.defineProperty 重写其 getter/setter。
    -每个属性关联一个 Dep 实例(依赖收集器)。
  2. 依赖收集(Dependency Collection):
    -当组件渲染时,会访问数据属性,触发 getter。
    -此时 Dep 会记录当前 Watcher(每个组件对应一个渲染 Watcher)。
  3. 派发更新(Dispatching Updates):
    -当数据被修改时,触发 setter。
    -Dep 通知所有关联的 Watcher 执行更新(如重新渲染组件)。
  4. 数组的特殊处理:
    -重写数组的 7 个方法(push/pop/shift/unshift/splice/sort/reverse),在调用这些方法时手动触发更新。
    -通过 proto 继承改写后的数组方法(或直接覆盖原型)。

代码简化示例:

javascript 复制代码
class Dep {
  constructor() {
    this.subs = new Set();
  }
  depend() {
    if (currentWatcher) this.subs.add(currentWatcher);
  }
  notify() {
    this.subs.forEach(watcher => watcher.update());
  }
}

function defineReactive(obj, key) {
  const dep = new Dep();
  let value = obj[key];
  Object.defineProperty(obj, key, {
    get() {
      dep.depend(); // 收集依赖
      return value;
    },
    set(newVal) {
      value = newVal;
      dep.notify(); // 触发更新
    }
  });
}

局限性:

  1. 无法检测新增/删除属性 → 需用 Vue.set/Vue.delete。
  2. 数组索引/长度修改无法监听 → 需用重写的方法或 Vue.set。
  3. 递归遍历对象性能损耗。

Vue 3.x 的响应式原理(基于 Proxy)

Vue 3 使用 Proxy 替代 Object.defineProperty,彻底解决 Vue 2 的痛点。

核心步骤:

  1. 代理对象(Reactive):
    -通过 Proxy 包裹目标对象,拦截 所有操作(增/删/改/查/遍历等)。
    -每个对象关联一个 ReactiveEffect 集合。
  2. 依赖收集:
    -当访问数据时,触发 get 拦截,收集当前活跃的 Effect(副作用函数)。
  3. 触发更新:
    -当修改数据时,触发 set 或 deleteProperty 拦截,通知所有关联的 Effect 重新执行。

代码简化示例:

javascript 复制代码
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); // 收集当前 Effect
}

function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;
  depsMap.get(key)?.forEach(effect => effect.run()); // 执行所有 Effect
}

const proxy = new Proxy(data, {
  get(target, key) {
    track(target, key); // 访问时收集依赖
    return Reflect.get(target, key);
  },
  set(target, key, value) {
    Reflect.set(target, key, value);
    trigger(target, key); // 修改时触发更新
    return true;
  }
});

优势:

  1. 支持监听动态新增/删除属性。
  2. 支持监听数组索引和长度变化。
  3. 惰性收集:仅代理访问到的属性,减少初始化开销。
  4. 统一处理对象/数组,无需特殊逻辑。

关键概念补充

  1. 副作用函数(Effect):
    -Vue 3 使用 ReactiveEffect 封装更新逻辑(相当于 Vue 2 的 Watcher)。
    -组件渲染、计算属性、侦听器都是副作用函数。
  2. 响应式 API:
    -reactive():创建深层次响应式对象(基于 Proxy)。
    -ref():将基本类型包装为 { value: ... } 的响应式引用(通过 .value 访问)。
    -computed/watch:基于 Effect 系统实现。
  3. 依赖清理:
    -每次执行 Effect 前清理旧依赖,避免无效更新(如条件分支变化时)。

总结对比

特性 Vue 2(Object.defineProperty) Vue 3(Proxy)
对象监听 递归遍历属性 直接代理整个对象
新增/删除属性 不支持(需 Vue.set) 支持
数组监听 需重写方法 直接支持索引修改
性能 初始化递归消耗大 按需代理,内存更优
兼容性 支持 IE9+ 不支持 IE(需 Polyfill)

Vue 3 的响应式系统独立为库 @vue/reactivity,可脱离框架使用。

相关推荐
bmxy小明同学19 分钟前
2026-10-11-幻觉治理
服务器·前端·javascript
Coder_张三31 分钟前
iOS 26 适配
前端·ios·swift
m0_5873830033 分钟前
无人自助拼豆系统落地开发实战指南 核心逻辑实现与部署经验分享
前端·javascript·vue.js·人工智能·经验分享·需求分析
ACP广源盛1392462567336 分钟前
硬件选型笔记|国产 PCIe4.0 交换芯片 IX8012@ACP,边缘 AI 设备 IO 扩展方案探讨
人工智能·笔记·硬件架构·pcie·国产芯片
zhaiyy38 分钟前
HTML Popover API 实践
前端·javascript·html
职豚求职小程序1 小时前
恒丰银行2026下半年笔试|考点&注意事项✅
笔记
OpsEye1 小时前
企业 AI 管理新需求:不仅要接入模型,还要看懂每一次调用
javascript·ai编程
牧艺1 小时前
SPA 也能像原生 App:View Transitions API 从原理到可上线实战
前端·javascript·css
Dovis(誓平步青云)1 小时前
现场问题先关闭还是先验收,建筑任务怎样处理依赖
前端·javascript·数据库·mysql·音视频
用户84298142418101 小时前
压缩 ≠ 加密:前端代码保护的三层实践与踩坑记录
前端·javascript