前端开发攻略---从源码角度分析Vue3的Propy比Vue2的defineproperty到底好在哪里。一篇文章让你彻底弄懂响应式原理。

1、思考

Vue的响应式到底要干什么?

  • 无非就是要知道当你读取对象的时候,要知道它读了。要做一些别的事情
  • 无非就是要知道当你修改对象的时候,要知道它改了。要做一些别的事情
  • 所以要想一个办法,把读取和修改的动作变成一个函数,读取和修改的时候分别调用对应的函数
  • 在ES6之,只能通过Object.defineproperty 给它变成一个get和set函数。当读取这个属性的时候运行get,修改这个属性的时候运行set

  • 在ES6之后,就能通过Porxy去代理整个对象

2、Vue2的做法 

针对某个对象中某个属性的做法

通过Object.defineProperty去针对某个对象的属性去进行监听                           

const obj = {a: 1,b: 2,c: {d: 3,e: 4,},
}// 保存初始值
let v = obj.aObject.defineProperty(obj, 'a', {get() {console.log('a', '读取')return v},set(val) {// 当原来的值与重新赋值的值不一样的时候才进行修改if (val !== v) {console.log('a', '更改了')v = val}},
})

当我们去读取 obj.a 这个属性的时候 get 函数 就会调用。

当我们去修改 obj.a 这个属性的时候 set 函数 就会调用。

针对某个对象中多个属性的做法

Vue2的源码中,有一个函数叫做 observe(观察器)。在这个函数中,去深度遍历对象中的每一个属性,给每一个属性添加 Object.defineProperty,这样就能对对象中的每一个属性叫做监听。这个过程就叫做 观察

const obj = {a: 1,b: 2,c: {d: 3,e: 4,},
}
// 辅助函数 判断这个值是不是一个对象
function _isObject(v) {return typeof v === 'object' && v !== null
}
function observe(obj) {for (const k in obj) {let v = obj[k]// 如果这一个属性仍然是一个对象的话,就需要深度遍历if (_isObject(v)) {observe(v)}Object.defineProperty(obj, k, {get() {console.log(k, '读取了')return v},set(val) {// 当原来的值与重新赋值的值不一样的时候才进行修改if (val !== v) {console.log(k, '更改了')v = val}},})}
}
observe(obj)

当我们去读取对象中的某个属性的时候 get 函数 就会调用。

当我们去修改对象中的某个属性的时候 set 函数 就会调用。

打印内容解释:

  • obj.a  =  3   更改
  • obj.c.d  = 4  先读取 obj.c 的值,再更改 obj.c.d 的值
  • obj.c.e   先读取 obj.c 的值,再读取 obj.c.e 的值

总结

  1. 在Vue2里面观察的方式就是 深度遍历每一个属性 把每一个属性的读取和赋值变成函数get和set。
  2. 在这种做法下有一个天生的缺陷,由于它是针对每个属性的监听,所以就必须要进行深度的遍历,这样会有效率损失。 
  3. 由于在 observe(obj) 观察这个步骤里边完成了深度遍历,也就是说在这个时间点里边,这些属性被我们监听到了都被改成get和set了
  4. 但是这一步一旦做完了之后。再去新增的话它就不知道了。比如 obj.qwertr = 3 对于这个属性而言,它就是没有监听的,因为监听的步骤已经结束了

  5. 这就是为什么Vue2它无法监听属性的新增,当然也包括属性的删除。它也收不到通知。因为在 Object.defineProperty 既不会运行get也不会运行set

3、Vue3的做法

其实核心道理都是一样的。无论是Vue2还是Vue3,都必须要把读取和赋值变成函数。只不过Vue3变成函数的方式不一样。在Vue3里面不会去对对象的每一个属性进行监听了,而是直接监听整个对象。将来不管是在这个对象中添加还是删除属性都不怕了。因为监听的是整个对象,这要动了这个对象就能收到通知。

做法

Vue3使用的是Proxy

const obj = {a: 1,b: 2,c: {d: 3,e: 4,},
}const proxy = new Proxy(obj, {// 读这个对象的属性的时候收到通知get(target, k) {// target就是obj,k是属性名let v = target[k]console.log(k, '读取')return v},// 修改这个对象的属性的时候收到通知set(target, k, val) {// target就是obj,k是属性名,val是新值if (target[k] !== val) {target[k] = valconsole.log(k, '更改')return target[k]}},// 删除对象的属性的时候收到通知deleteProperty(target, k, val) {console.log(k, '删除')return target[k]},
})

会产生一个代理对象propx,将来去读属性也好,重新给属性赋值也好都是通过这个代理对象去做的。

总结

  1. Proxy 对象可以直接代理整个对象,而不需要遍历对象属性进行劫持,这样可以减少运行时的性能开销。在 Vue 2 中,由于每个属性都需要单独设置 get 和 set,对于大量的属性或嵌套属性,这种劫持可能会导致性能下降。
  2. 另外,使用 Proxy 的方式更符合现代 JavaScript 的发展趋势,更好地利用了 JavaScript 引擎的优化。

4、总结

综上所述,Vue 3 中使用 Proxy 对象代替了 Vue 2 中的 Object.defineProperty,带来了更强大、更灵活和更高效的属性拦截和代理功能,同时也提升了开发体验和调试效率。这些改进使得 Vue 3 在处理 Props 的方式更加现代化和优雅,提升了整体的性能和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/820463.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

xcode c++项目设置运行时参数

在 Xcode 项目中,你可以通过配置 scheme 来指定在运行时传递的参数。以下是在 Xcode 中设置运行时参数的步骤: 打开 Xcode,并打开你的项目。在 Xcode 菜单栏中,选择 "Product" -> "Scheme" -> "E…

每日一练

这题我主要用的思想是:动态规划 1.状态表示&#xff1a;以i位置为结尾的字符串是否可以用字典表示&#xff0c;然后就可以拆分成 j ~ i 为字典中的最后一个单词&#xff0c;此时 0 < j < i (1.有可能全部为字典的一个单词&#xff0c;2.有可能只有一个字母的单词)&#x…

光纤网络的星际旅行:SFP与QSFP光模块的技术演进

&#x1f389;光模块作为完成光电转换的光器件&#xff0c;在光通信网络中必不可少&#xff0c;常见的有千兆/万兆光模块、SFP/SFP/QSFP28光模块等&#xff0c;那你知道这些光模块都是如何分类的吗&#xff1f;另外还有哪些类型&#xff1f;接下来我会在本文详细介绍光模块是如…

平台工程在企业数字化转型中的战略价值

要建设成功、有弹性和面向未来的平台&#xff0c;需要做到这三点&#xff1a;了解需求、预测可能面临的挑战并制定经得起时间考验的解决方案。 了解需求是指理解利益相关者的要求和目标&#xff0c;无论他们是最终用户、开发人员还是平台生态系统中的其他相关方。这包括开展全面…

排序算法。

冒泡排序: 基本&#xff1a; private static void sort(int[] a){for (int i 0; i < a.length-1; i) {for (int j 0; j < a.length-i-1; j) {if (a[j]>a[j1]){swap(a,j,j1);}}}} private static void swap(int[] a,int i,int j){int tempa[i];a[i]a[j];a[j]temp;} …

MathType安装导致的Word粘贴操作出现运行时错误‘53’:文件未找到:MathPage.WLL

MathType安装导致的Word粘贴操作出现运行时错误‘53’&#xff1a;文件未找到&#xff1a;MathPage.WLL 解决方案 1、确定自己电脑的位数&#xff1b; 2、右击MathType桌面图标&#xff0c;点击“打开文件所在位置”&#xff0c;然后找到MathPage.WLL &#xff0c;复制一份进行…

二级综合医院云HIS系统源码,B/S架构,采用JAVA编程,集成相关医保接口

二级医院云HIS系统源码 云HIS系统是一款满足基层医院各类业务需要的健康云产品。该产品能帮助基层医院完成日常各类业务&#xff0c;提供病患预约挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生工作站和护士工作站等一系列常规功能&#xff0c;还能与公卫…

【御控物联】Java JSON结构转换(3):对象To对象——多层属性重组

文章目录 一、JSON结构转换是什么&#xff1f;二、案例之《JSON对象 To JSON对象》三、代码实现四、在线转换工具五、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换&#xff0c;生成新的JS…

【电控笔记6.2】拉式转换与转移函数

概要 laplace&#xff1a;单输入单输出&#xff0c;线性系统 laplace 传递函数 总结

Spring GA、PRE、SNAPSHOT 版本含义及区别

GA:General Availability: 正式发布的版本&#xff0c;推荐使用&#xff08;主要是稳定&#xff09;&#xff0c;与maven的releases类似&#xff1b; PRE: 预览版,内部测试版。主要是给开发人员和测试人员测试和找BUG用的&#xff0c;不建议使用&#xff1b; SNAPSHOT: 快照…

算法学习系列(四十九):最长上升子序列模型(一)

目录 引言一、最长上升子序列二、怪盗基德的滑翔翼三、登山四、合唱队形五、友好城市六、最大上升子序列和 引言 今天学习的是最长上升子序列模型&#xff0c;这种模型我觉得就是我之前说过的就是相当于记忆的过程&#xff0c;记住遇到这种题是用这种模型&#xff0c;下次遇见…

打开电脑底部导航栏的任务

from pywinauto import Application app Application("uia").connect(path"explorer") app["任务栏"].print_control_identifiers() task app["任务栏"].child_window(title"酷狗音乐", auto_id"D:\soft\kugou\KGMus…

Proxmox VE 实现批量增加多网络

前言 实现批量创建多网络&#xff0c;更改主机名称&#xff0c;hosts解析 初始化网卡&#xff0c;主机名称&#xff0c;hosts解析&#xff0c;重启网卡 我的主机六个网卡&#xff0c;使用的有四个网卡&#xff0c;以下一键创建和初始化主机名称我是以硬件的SN号最为主机的名…

Matlab调C/C++简单模板例子

如果你是需要快速搭建一个matlab调c/c环境&#xff0c;这篇文章可以参考 有了c代码&#xff0c;想在matlab里面调用&#xff0c;可以参考我这个模板 matlab调用代码&#xff1a; clear all close all clcinput1 1; input2 2;[output1,output2] mexfunction(input1,input2);…

普通人做抖音小店真的能赚钱吗?可以,但更取决于个人

大家好&#xff0c;我是电商花花。 现在做抖音小店的基本上都是一些新商家&#xff0c;对于我们众多零基础的朋友来说&#xff0c;是期待也是一份挑战。 抖音小店作为一个充满机会的新兴平台&#xff0c;许多人都欣喜的投入其中&#xff0c;期望能够借此来改变自己的命运&…

西门子电动阀门

一、西门子电动调节阀 二、西门子电动调节蝶阀 1、阀门 2、执行器

客户资料不翼而飞?企业数据保护攻略

在数字化经济时代&#xff0c;企业的客户资料等同于商业生命线&#xff0c;一旦泄露&#xff0c;后果不堪设想。例如&#xff0c;2017年Equifax的数据泄露事件&#xff0c;造成超过1.4亿用户的个人信息外泄&#xff0c;不仅给用户带来风险&#xff0c;也让公司名誉受损&#xf…

BackTrader 中文文档(二)

原文&#xff1a;www.backtrader.com/ 概念 平台概念 原文&#xff1a;www.backtrader.com/docu/concepts/ 这是平台某些概念的集合。它试图收集可在使用平台时有用的信息片段。 开始之前 所有小代码示例都假设以下导入可用&#xff1a; import backtrader as bt import ba…

移植speexdsp到OpenHarmony标准系统④

五、在OpenHarmony编译体系下增量编译Speexdsp 建议先增量编译生成三方库的动态链接库和可执行文件,验证是否成功把三方库加入OpenHarmonybian编译体系。 成功编译出so和可执行文件&#xff0c;即成功把三方库加入到ohos编译体系。之后还要验证三方库在ohos运行&#xff0c;功…

英语新概念2-回译法-lesson8

乔桑德斯有着我们镇上最漂亮的花园。附近的每一个人每年都参加“最美花园比赛”&#xff0c;但是每年都是乔赢得比赛。比尔芙丽丝的花园比乔的花园大&#xff0c;但是乔的花园更有趣。他有整洁的小径以及一座木桥架在一个池塘上。我也喜欢花园&#xff0c;但是我不喜欢辛勤劳作…