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

Vue3响应式原理【通俗理解】

核心流程就三步:

  1. 读取数据时:偷偷记录“谁在用我”(依赖收集/track)
  2. 修改数据时:通知所有用我的人“我变了”(派发更新/trigger)
  3. 用proxy来拦截“读取”和“修改”这两个动作。

Proxy 是什么

一句话:Proxy 是 JavaScript 原生提供的一个"拦截器",它能在你对一个对象做任何操作(读、写、删除、遍历……)的时候,插一脚进去,执行你自定义的逻辑。

打个比方:你去酒店前台拿快递,前台小姐姐就是 Proxy。你不能直接进仓库翻,所有操作都经过她。她可以在给你快递之前登记一下(依赖收集),也可以在你寄快递时通知别人(触发更新)。

基本语法

constproxy=newProxy(target,handler)
  • target:你要代理的原始对象
  • handler:一个对象,里面定义你要拦截哪些操作

handler 里常用的拦截方法(叫 trap):

constobj={name:'张三',age:25}constproxy=newProxy(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.age=30// 输出: 有人把 age 改成了 30deleteproxy.age// 输出: 有人删除了 age'name'inproxy// 输出: 有人检查 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')value=newVal}})// 问题1:新增属性监听不到data.newProp='hello'// 没有任何拦截,Vue 2 里必须用 Vue.set()// 问题2:删除属性监听不到deletedata.count// 没有任何拦截,Vue 2 里必须用 Vue.delete()// 问题3:数组索引修改监听不到constarr=[1,2,3]arr[0]=999// 监听不到,Vue 2 里这个操作不会触发视图更新

再看 Proxy 怎么解决这些问题:

constdata=reactive({count:0})// 新增属性 → 自动触发 set trap ✅data.newProp='hello'// 删除属性 → 自动触发 deleteProperty trap ✅deletedata.count// 数组操作 → 全部能拦截 ✅constarr=reactive([1,2,3])arr[0]=999// 触发 setarr.push(4)// 触发 set(length 和新索引都能捕获)

对比总结

特性 Object.defineProperty Proxy ───────────────────────────────────────────────────────── 监听新增属性 ❌ 不行 ✅ 可以 监听删除属性 ❌ 不行 ✅ 可以 监听数组索引 ❌ 不行 ✅ 可以 监听粒度 单个属性 整个对象 需要递归初始化 ✅ 需要深度遍历 ❌ 按需代理(懒递归) 性能 初始化开销大 访问时才代理,更快

最后一点"懒递归"值得说一下。Vue 2 在初始化时必须递归遍历整个对象的所有嵌套属性,全部用defineProperty劫持一遍。而 Vue 3 的 Proxy 只在你真正访问到某个嵌套对象时,才对它创建代理:

conststate=reactive({user:{address:{city:'北京'}}})// 只有当你真正读到 state.user.address 时// Vue 3 才会对 address 这个对象创建 Proxy// 如果你从来不访问它,就不会有任何开销

这就是 Vue 3 性能更好的原因之一。

简单说,Proxy 就是 JavaScript 给你的一个"万能拦截器",Vue 3 用它来监听数据的一切变化,比 Vue 2 的方案更全面、更高效、代码也更简洁。

http://www.cnnetsun.cn/news/1833408.html

相关文章:

  • 三步掌握网络资源下载:揭秘res-downloader的智能嗅探技术
  • Python 批量导出数据库数据至 Excel 文件透
  • Spring AOP(二) Spring AOP 完整指南
  • 钢结构厂房通风排烟天窗选型与安装要点(附国标图集要求)
  • 2025届毕业生推荐的六大AI写作网站横评
  • S32K3XX时钟树实战:从EB配置到外设时钟精准分配
  • MoneyPrinterPlus:AI视频创作革命,让普通人也能成为短视频创作大师
  • 如何用kill-doc脚本轻松下载各大文库文档:三步告别广告和登录验证
  • 限流规则写死=技术负债!用OpenTelemetry+Grafana Loki构建可观测熔断决策闭环(附2024最新eBPF内核级流量采样方案)
  • 从“已爆发”到“将爆发”——Infoseek舆情系统重构预警的时间线
  • AI原生研发决策树不是流程图,而是生存指南:20年踩过137次技术栈陷阱后凝练的6个不可逆判定节点(含SLO反向约束校验机制)
  • ROS2与ROS1多机通信对比:用Domain ID替代Master URI的新玩法
  • DWT基础应用与获取程序运行时间Debug练习(上)
  • WinCC7.5+Telegraf+Influxdb 3.0 Core:通过OPC UA方式WinCC数据直接同步数据到Influxdb
  • Ubuntu 22.04 + PyTorch 2.3 环境:PyG 2.5+ 一键安装与版本兼容性实战
  • 从手机充电器到电动车BMS:图解多电源系统中电流回路的3个关键设计原则
  • 我用 AI 辅助开发了一系列小工具():文件提取工具邮
  • 如何轻松玩转怀旧Flash游戏?这个免费工具帮你搞定一切!
  • Mysql的行级锁到底是怎么加的?谌
  • CSS变量与自定义属性
  • 我们为什么放弃了ActiveMQ,转向了Pulsar?
  • RAG详解:让大模型看见你的私有知识
  • 整合素家族核心靶点解析:CD51(Integrin αv)的分子机制与药物研发技术前瞻
  • Pandas显示设置全攻略:如何让数据表格在Jupyter Notebook中更美观(附常见问题解决)
  • 事件驱动化技术中的事件发布事件订阅与事件处理
  • 计算机毕业设计:Python空气质量智能评估与预测平台 Django框架 Spark 线性回归 可视化 大数据 机器学习 深度学习(建议收藏)✅
  • Upscayl图像放大GPU加速深度优化:告别Vulkan兼容性困扰
  • Gemma-3-270m应用场景:政务公文润色、政策文件要点速读生成案例
  • 酷安UWP桌面客户端:Windows平台上的酷安社区完整体验指南
  • 日本Shopify消费趋势分析:樱花季与新生活季正在带火哪些品类?