核心流程就三步读取数据时偷偷记录“谁在用我”依赖收集/track修改数据时通知所有用我的人“我变了”派发更新/trigger用proxy来拦截“读取”和“修改”这两个动作。Proxy 是什么一句话Proxy 是 JavaScript 原生提供的一个拦截器它能在你对一个对象做任何操作读、写、删除、遍历……的时候插一脚进去执行你自定义的逻辑。打个比方你去酒店前台拿快递前台小姐姐就是 Proxy。你不能直接进仓库翻所有操作都经过她。她可以在给你快递之前登记一下依赖收集也可以在你寄快递时通知别人触发更新。基本语法constproxynewProxy(target,handler)target你要代理的原始对象handler一个对象里面定义你要拦截哪些操作handler 里常用的拦截方法叫 trapconstobj{name:张三,age:25}constproxynewProxy(obj,{// 拦截读取get(target,key){console.log(有人读取了${key})returntarget[key]},// 拦截写入set(target,key,value){console.log(有人把${key}改成了${value})target[key]valuereturntrue},// 拦截删除deleteProperty(target,key){console.log(有人删除了${key})deletetarget[key]returntrue},// 拦截 key in objhas(target,key){console.log(有人检查${key}是否存在)returnkeyintarget}})proxy.name// 输出: 有人读取了 name → 张三proxy.age30// 输出: 有人把 age 改成了 30deleteproxy.age// 输出: 有人删除了 agenameinproxy// 输出: 有人检查 name 是否存在看到了吧所有对proxy的操作都被你拦截了你想在里面干啥都行。为什么 Vue 3 要用 Proxy先看 Vue 2 用的Object.defineProperty有什么问题// Vue 2 的方式逐个属性劫持constdata{count:0}Object.defineProperty(data,count,{get(){console.log(读取 count)returnvalue},set(newVal){console.log(修改 count)valuenewVal}})// 问题1新增属性监听不到data.newProphello// 没有任何拦截Vue 2 里必须用 Vue.set()// 问题2删除属性监听不到deletedata.count// 没有任何拦截Vue 2 里必须用 Vue.delete()// 问题3数组索引修改监听不到constarr[1,2,3]arr[0]999// 监听不到Vue 2 里这个操作不会触发视图更新再看 Proxy 怎么解决这些问题constdatareactive({count:0})// 新增属性 → 自动触发 set trap ✅data.newProphello// 删除属性 → 自动触发 deleteProperty trap ✅deletedata.count// 数组操作 → 全部能拦截 ✅constarrreactive([1,2,3])arr[0]999// 触发 setarr.push(4)// 触发 setlength 和新索引都能捕获对比总结特性 Object.defineProperty Proxy ───────────────────────────────────────────────────────── 监听新增属性 ❌ 不行 ✅ 可以 监听删除属性 ❌ 不行 ✅ 可以 监听数组索引 ❌ 不行 ✅ 可以 监听粒度 单个属性 整个对象 需要递归初始化 ✅ 需要深度遍历 ❌ 按需代理懒递归 性能 初始化开销大 访问时才代理更快最后一点懒递归值得说一下。Vue 2 在初始化时必须递归遍历整个对象的所有嵌套属性全部用defineProperty劫持一遍。而 Vue 3 的 Proxy 只在你真正访问到某个嵌套对象时才对它创建代理conststatereactive({user:{address:{city:北京}}})// 只有当你真正读到 state.user.address 时// Vue 3 才会对 address 这个对象创建 Proxy// 如果你从来不访问它就不会有任何开销这就是 Vue 3 性能更好的原因之一。简单说Proxy 就是 JavaScript 给你的一个万能拦截器Vue 3 用它来监听数据的一切变化比 Vue 2 的方案更全面、更高效、代码也更简洁。