《Vue3 从入门到大神05篇》Vue3 响应式原理初探 —— 从 Object.defineProperty 到 Proxy
前言如果说Composition API 是 Vue3 的表象革新那么响应式系统的重构才是 Vue3 的灵魂升级。Vue2 的响应式被无数开发者“吐槽过”❌ 无法监听对象新增属性❌ 无法监听数组索引变化❌$set/$delete用得心累而 Vue3 用Proxy Reflect 一次性解决了这些问题。今天这篇文章我们就从原理图 → 代码对比 → 手写简易版彻底搞懂 Vue3 的响应式核心。一、Vue2 响应式Object.defineProperty 的局限1️⃣ Vue2 响应式简化模型function defineReactive(obj, key, val) { Object.defineProperty(obj, key, { get() { // 依赖收集 return val }, set(newVal) { // 通知更新 val newVal } }) }2️⃣ Vue2 的致命问题问题表现新增属性无法监听需Vue.set删除属性无法监听需Vue.delete数组索引无法监听性能初始化递归遍历所有属性根本原因Object.defineProperty只能劫持已有属性。二、Vue3 响应式Proxy 的降维打击1️⃣ Proxy 是什么一句话解释Proxy 是对整个对象的“代理”而不是对单个属性的“修补”。const obj { count: 0 } const proxy new Proxy(obj, { get(target, key, receiver) { console.log(get:, key) return Reflect.get(target, key, receiver) }, set(target, key, value, receiver) { console.log(set:, key, value) return Reflect.set(target, key, value, receiver) } })2️⃣ 拦截能力对比重点行为Vue2Vue3读取属性✅✅新增属性❌✅删除属性❌✅数组索引❌✅length 变化❌✅Map / Set❌✅✅Proxy 能拦截 13 种操作几乎覆盖所有对象行为。三、Reflect为什么 Vue3 一定要用它1️⃣ Reflect 的作用能力说明统一 API替代obj[key]返回值语义成功 / 失败与 Proxy 完美配合保证 receiver 正确指向2️⃣ 错误示例 vs 正确示例❌ 不推荐get(target, key) { return target[key] }✅ Vue3 推荐get(target, key, receiver) { return Reflect.get(target, key, receiver) }原因保证this指向正确兼容原型链行为更规范四、Vue3 响应式原理图解文字版组件渲染 ↓ 读取响应式数据get ↓ 依赖收集track ↓ 建立 数据 ↔ 组件 关联 ↓ 数据变化set ↓ 触发依赖trigger ↓ 组件重新渲染核心函数reactive()→ 创建响应式对象effect()→ 副作用函数组件渲染track()→ 依赖收集trigger()→ 触发更新五、手写一个 Mini Vue3 响应式面试高频1️⃣ 实现 reactivefunction reactive(obj) { return new Proxy(obj, { get(target, key, receiver) { track(target, key) return Reflect.get(target, key, receiver) }, set(target, key, value, receiver) { const result Reflect.set(target, key, value, receiver) trigger(target, key) return result } }) }2️⃣ 简化版 effect / track / triggerconst targetMap new WeakMap() function track(target, key) { let depsMap targetMap.get(target) if (!depsMap) { depsMap new Map() targetMap.set(target, depsMap) } let dep depsMap.get(key) if (!dep) { dep new Set() depsMap.set(key, dep) } dep.add(effect) } function trigger(target, key) { const depsMap targetMap.get(target) if (!depsMap) return const effects depsMap.get(key) effects?.forEach(fn fn()) } let effect effect () { console.log(组件重新渲染) }✅ 这就是 Vue3 响应式的最小实现模型。六、Vue3 响应式的三大优势总结✅ 1. 真正的数据监听const state reactive({ count: 0 }) state.newProp 123 // ✅ 可监听✅ 2. 性能更好初始化时不递归访问时才代理✅ 3. 代码更优雅不再需要$set/$delete心智负担大幅降低七、面试高频问答建议背Q1Vue2 为什么不能监听新增属性因为Object.defineProperty只能劫持已有属性。Q2Vue3 为什么用 ProxyProxy 可以拦截整个对象支持新增、删除、数组变化。Q3Reflect 的作用是什么提供统一的对象操作 API保证 Proxy 行为正确。