当前位置: 首页 > article >正文

Vue3响应式原理解析

一、什么是响应式?

想象一个 Excel 表格:当单元格 A1 的值变化时,依赖 A1 的公式(如 SUM(A1, B1))会自动重新计算。Vue3 的响应式系统正是实现了这种“自动更新”的能力——当数据变化时,依赖它的视图或计算属性会自动更新。


二、Vue3 响应式的核心实现

1. 底层工具:Proxy 与 Reflect

Vue3 使用 Proxy 代替 Vue2 的 Object.defineProperty,因为它能拦截对象的所有操作(如属性读取、新增、删除等),而无需预先定义属性149。

const obj = { a: 1 };
const proxy = new Proxy(obj, {
  get(target, key) {
    console.log('读取属性:', key);
    return Reflect.get(target, key); // 使用 Reflect 保证 this 指向正确
  },
  set(target, key, value) {
    console.log('设置属性:', key, value);
    return Reflect.set(target, key, value);
  }
});

2. 响应式对象:reactive()

reactive() 函数将普通对象转为响应式对象,内部通过 Proxy 实现:

function reactive(target) {
  return new Proxy(target, {
    get(target, key) {
      track(target, key); // 收集依赖
      const res = Reflect.get(target, key);
      // 递归处理嵌套对象
      return isObject(res) ? reactive(res) : res;
    },
    set(target, key, value) {
      Reflect.set(target, key, value);
      trigger(target, key); // 触发更新
      return true;
    }
  });
}

关键点

  • 深层响应:嵌套对象会被递归代理1。

  • 避免重复代理:通过 WeakMap 缓存已代理对象10。


3. 副作用函数:effect()

副作用函数(如渲染函数)会在依赖的响应式数据变化时重新执行:

let activeEffect;
function effect(fn) {
  const _effect = () => {
    activeEffect = _effect; // 标记当前正在执行的副作用函数
    fn();
    activeEffect = null;
  };
  _effect(); // 立即执行一次以收集依赖
}

// 示例
effect(() => {
  console.log('数据变化了:', state.a);
});

4. 依赖收集与触发更新

(1) 数据结构
  • targetMapWeakMap,键为响应式对象,值为 depsMap

  • depsMapMap,键为对象的属性名,值为 dep(依赖集合)。

  • depSet,存储所有依赖该属性的副作用函数210。

(2) track():收集依赖

在读取属性时,将当前副作用函数加入依赖集合:

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);
}
(3) trigger():触发更新

在设置属性时,执行所有依赖该属性的副作用函数:

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

三、Vue3 对比 Vue2 的优势49

特性Vue2 (Object.defineProperty)Vue3 (Proxy)
检测新增属性需手动调用 Vue.set()自动支持
数组索引修改需重写数组方法直接通过下标修改即可
嵌套对象处理需递归初始化按需代理(惰性处理)
性能初始化时递归遍历所有属性动态代理,按需收集依赖

四、实战示例

1. 基础响应式

const state = reactive({ count: 0 });
effect(() => {
  console.log('count 值变为:', state.count);
});
state.count++; // 触发控制台输出

2. 嵌套对象

const obj = reactive({ 
  foo: { bar: 1 } 
});
effect(() => {
  console.log(obj.foo.bar); // 深层属性仍可响应
});
obj.foo.bar = 2; // 触发更新

五、总结

Vue3 的响应式系统通过 Proxy 拦截对象操作,结合 依赖收集(track) 与 触发更新(trigger) 实现了高效的数据绑定。相比 Vue2,它解决了动态属性、数组操作等痛点,且性能更优。理解其核心原理有助于更好地使用 Vue3 开发复杂应用。

想深入学习可参考:Vue3 响应式官方文档


http://www.kler.cn/a/567282.html

相关文章:

  • docker使用代理的简单配置
  • 在 Vim 中查找一个单词的命令
  • JAVA面试_进阶部分_23种设计模式总结
  • Vue.js 组件开发全面详解及应用案例
  • 云创智城YunCharge 新能源二轮、四轮充电解决方案(云快充、万马爱充、中电联、OCPP1.6J等多个私有单车、汽车充电协议)之充电占位解决方案
  • 【时序预测】在线学习:算法选择(从线性模型到深度学习解析)
  • 2015 - 2024年国外与中国博士招生毕业人数趋势现状分析2025.2.26
  • Python基于Django的音乐推荐系统的设计与实现(附源码,文档说明)
  • android::hardware::configureRpcThreadpool使用介绍
  • 6. Nginx 动静分离配置案例(附有详细说明+配图)
  • 游戏引擎学习第129天
  • 用win+python+pycharm 开发一个项目,负责档案审核
  • Qt常用控件之微调框QSpinBox
  • Web自动化之Selenium添加网站Cookies实现免登录
  • 金融支付行业技术侧重点
  • 解锁 indexOf、substring 和 JSON.stringify:从小程序图片上传看字符串魔法 ✨
  • 梯度下降法(Gradient Descent) -- 现代机器学习的血液
  • 【项目管理】基于 C 语言的 QQ 聊天室实现(TCP + 多线程 + SQLite3)后续部分代码优化
  • readline模块详解!!【Node.js】
  • Github 2025-03-01 开源项目月报 Top19