《Vue3 从入门到大神33篇》Vue3 源码详解(三):响应式核心思想——从 Object.defineProperty 到 Proxy 本篇关键词响应式本质、Proxy、依赖收集、effect、track、trigger难度等级⭐⭐⭐⭐☆偏底层但全程带 Demo工程价值读懂这一篇你能手写简易状态管理库、精准定位响应式 Bug、面试秒杀 90% 候选人。一、开篇为什么 Vue3 要抛弃 Object.defineProperty如果你用过 Vue2一定写过这样的代码data() { return { list: [1, 2, 3] } }然后你发现this.list[0] 99 // ❌ 不触发更新 this.list.length 0 // ❌ 不触发更新 delete this.obj.a // ❌ 不触发更新Vue2 的解决方案是set、delete、重写数组方法。这些不是“特性”而是补丁。Vue2 响应式的本质缺陷Object.defineProperty只能做到✅ 劫持已有属性❌ 无法监听新增 / 删除属性❌ 无法监听数组索引 / length❌ 需要递归遍历对象性能差结论Vue2 的响应式是“后天修补出来的”。二、Vue3 的解法Proxy 带来的降维打击Vue3 使用Proxy一句话概括其优势Proxy 是对整个对象的拦截而不是对属性的拦截。Proxy 最直观的 Demo先感性理解const obj { count: 0 } const proxy new Proxy(obj, { get(target, key, receiver) { console.log(读取 ${key}) return Reflect.get(target, key, receiver) }, set(target, key, value, receiver) { console.log(修改 ${key} ${value}) return Reflect.set(target, key, value, receiver) } }) proxy.count // 读取 count proxy.count 1 // 修改 count 1✅ 新增属性能拦截✅ 删除属性能拦截✅ 数组索引能拦截✅ 嵌套对象懒代理后面讲三、响应式系统的灵魂三问源码级思维在阅读 Vue3 响应式源码前必须先回答三个问题谁用了这个数据依赖收集数据变了通知谁依赖触发如何避免无限循环调度控制Vue3 的答案非常优雅概念对应源码依赖收集track()触发更新trigger()副作用函数effect()四、手写 Mini ReactiveVIP 核心环节不先写 Demo直接读源码 劝退。下面我们用不到 30 行代码实现一个最简响应式系统。Step 1存储依赖的数据结构// 存储所有副作用 const targetMap new WeakMap() // 当前正在执行的 effect let activeEffect null设计说明WeakMaptarget, Mapkey, Seteffect为什么用WeakMap防止内存泄漏为什么用Set防止重复收集Step 2track —— 依赖收集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) }一句话解释把“当前正在执行的副作用函数”存到“目标对象的指定属性”下。Step 3trigger —— 触发更新function trigger(target, key) { const depsMap targetMap.get(target) if (!depsMap) return const dep depsMap.get(key) if (dep) { dep.forEach(effect effect()) } }一句话解释找到“目标对象指定属性的所有副作用”挨个执行。Step 4effect —— 副作用容器function effect(fn) { activeEffect fn fn() // 执行一次触发 track activeEffect null }关键点执行fn()时内部读取响应式数据触发get→ 调用track完成依赖收集Step 5reactive —— 创建响应式对象function reactive(obj) { return new Proxy(obj, { get(target, key, receiver) { const result Reflect.get(target, key, receiver) track(target, key) return result }, set(target, key, value, receiver) { const result Reflect.set(target, key, value, receiver) trigger(target, key) return result } }) }Step 6完整 Demo 跑起来 const state reactive({ count: 0 }) effect(() { console.log(count , state.count) }) state.count // 控制台自动打印count 1 state.count 5 // 控制台自动打印count 5✅恭喜你你已经理解了 Vue3 响应式的 80% 核心逻辑。五、对照 Vue3 源码你写的就是简化版源码你现在写的代码本质上就是packages/reactivity/src/ ├── effect.ts ← effect / track / trigger ├── reactive.ts ← reactive() └── baseHandlers.ts ← Proxy handlers源码中的关键对应关系手写Vue3 源码activeEffecteffectStacktrack()track()trigger()trigger()depsDep类型区别只是源码多了调度器、递归代理、边界处理。六、工程视角为什么这样设计VIP 重点1️⃣ 为什么用 WeakMapWeakMap → key 必须是对象好处对象销毁 → 键值自动回收避免手动清理依赖Vue2 的痛点2️⃣ 为什么 effect 要支持嵌套effect(() { effect(() { console.log(state.count) }) })Vue3 使用effectStack​ 解决effectStack.push(effect) activeEffect effect3️⃣ 为什么需要调度器Scheduler试想state.count state.count你不希望触发两次更新。Vue3 通过queueJobnextTickflushPostFlushCbs实现异步批量更新。下一篇详细讲七、调试实战在源码中验证你的理解回到第二篇搭建的环境在以下位置打断点packages/reactivity/src/effect.ts重点关注track()何时被调用trigger()如何遍历depactiveEffect的变化过程你会发现源码逻辑和你手写的 Mini Reactive 几乎一致。八、面试高频追问收藏级Proxy 一定能监听到所有变化吗不能。Map、Set需要单独处理mutableHandlersvscollectionHandlersVue3 为什么还要 refProxy 无法代理基本类型ref本质是{ value }对象的语法糖。track 和 trigger 一定是同步的吗不一定。计算属性、watch、组件更新都可能被调度延迟。九、本篇总结✅ Vue3 响应式 Proxy WeakMap Effect✅ 核心流程读取收集 → 修改触发​✅ 手写 Mini Reactive 是读源码的最短路径✅ 工程中理解调度器、嵌套 effect、内存管理一句话升华Vue3 的响应式不是“魔法”而是一个设计极其精巧的观察者模式 代理模式组合。十、下一篇预告《Vue3 源码详解四reactive 与 ref 源码解析搞懂响应式对象创建过程》

相关新闻

最新新闻

Agent之Skill:dashi-ppt-skill的简介、安装和使用方法、案例应用之详细攻略

Agent之Skill:dashi-ppt-skill的简介、安装和使用方法、案例应用之详细攻略

Agent之Skill:dashi-ppt-skill的简介、安装和使用方法、案例应用之详细攻略 目录 dashi-ppt-skill的简介 1、特点 dashi-ppt-skill的安装和使用方法 1、安装 2、使用方法 dashi-ppt-skill的案例应用 案例一:根据文档生成浏览器可编辑的演示文稿—…

2026/7/19 0:11:15
Agent之skills:google/skills的简介、安装和使用方法、案例应用之详细攻略

Agent之skills:google/skills的简介、安装和使用方法、案例应用之详细攻略

Agent之skills:google/skills的简介、安装和使用方法、案例应用之详细攻略 目录 google/skills的简介 1、特点 2、核心内容 google/skills的安装和使用方法 1、安装 2、使用方法 Google Skills的案例应用 案例一:安装 Google Skills 仓库—安装 …

2026/7/19 0:11:15
原汁机渣汁分离口感细腻,纯正果蔬原汁入口无残渣

原汁机渣汁分离口感细腻,纯正果蔬原汁入口无残渣

原汁机渣汁分离口感细腻,纯正果蔬原汁入口无残渣每天在厨房里折腾半小时,末了喝到嘴里还带着渣渣的果蔬汁,这样的体验确实让人头疼。直到接触蓝宝BP-YJ06多功能饮品机,才真正理解什么叫“渣汁分离口感细腻”——纯正果蔬原汁入口无…

2026/7/19 0:11:15
《AI 渐进编程》之十九:Agent 为什么也会制造技术债?

《AI 渐进编程》之十九:Agent 为什么也会制造技术债?

很多人使用 Agent 编程时,会有一个期待: AI 写代码更快,项目维护成本是不是也会更低? 不一定。 现在也常听到一些说法:某些项目的代码几乎全部由 AI 生成,甚至“100% 由 AI 写代码”。 但这里要区分两件事…

2026/7/19 0:11:15
现代C++ :constexpr:一个常态的世界

现代C++ :constexpr:一个常态的世界

引言我们已经连续讲了几讲比较累人的编译期编程了。今天我们还是继续这个话题,但是,相信今天学完之后,你会感觉比之前几讲要轻松很多。C 语言里的很多改进,让我们做编译期编程也变得越来越简单了。初识 constexpr我们先来看一些例…

2026/7/19 0:11:15
微服务进阶:服务网格与Istio

微服务进阶:服务网格与Istio

541|微服务进阶:服务网格与Istio 上篇文章我们聊了微服务的基本概念和拆分方法。 但微服务多了,问题也多了: 服务之间怎么通信? 怎么监控每个服务的调用链路? 熔断、限流、重试怎么做? 安全认证怎么统一? 以前这些都靠SDK库(比如Hystrix、Feign),每个服务都要集成…

2026/7/19 0:06:15

月新闻