欢迎光临
我们一直在努力

《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️⃣ 拦截能力对比(重点)

行为

Vue2

Vue3

读取属性

✅

✅

新增属性

❌

✅

删除属性

❌

✅

数组索引

❌

✅

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️⃣ 实现 reactive

function 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 / trigger

const 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

  • 心智负担大幅降低


七、面试高频问答(建议背)

Q1:Vue2 为什么不能监听新增属性?

因为 Object.defineProperty只能劫持已有属性。

Q2:Vue3 为什么用 Proxy?

Proxy 可以拦截整个对象,支持新增、删除、数组变化。

Q3:Reflect 的作用是什么?

提供统一的对象操作 API,保证 Proxy 行为正确。

赞(0)
未经允许不得转载:171主机测评 » 《Vue3 从入门到大神05篇》Vue3 响应式原理初探 —— 从 Object.defineProperty 到 Proxy
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址