vue2的响应式原理学“废”了吗?继续观摩vue3响应式原理Proxy

vue3响应式原理

一文了解Vue3的响应式原理

  • 一、🟩回顾Object.defineProperty
  • 二、🟨Proxy基本使用
  • 三、🟦学习Proxy语法:Reflect
  • 四、🟧Vue3如何用Proxy实现响应式
    • 1、实现响应式
    • 2、Proxy总结
      • (1)深度监听,性能更好
      • (2)可监听 新增/删除 属性
      • (3)可监听数组变化
    • 3、两者对比
  • 五、🟪结束语

之前写过一篇文章谈论 vue2.x响应式原理,但因为 vue3 也来了,紧跟着 vue3 的步伐,周一开始学起了 vue3 的响应式原理。

大家应该都听过, vue3proxy 来解决响应式原理,同时它解决了 vue2Object.definePropery 存在的一些问题,但同时也带来了一些问题。

在下面的这篇文章中,将讲解关于 vue3proxy 如何实现响应式,以及带来的一些问题。一起来学习吧💯

一、🟩回顾Object.defineProperty

这里需要大家对 ObjectProperty 的知识点有一个预先了解,如有需要了解可点击文章进行查看~

现在,我们来回顾下 Object.defineProperty缺点:

  • 深度监听时需要一次性递归;
  • 无法监听新增属性/删除属性(需要配合 Vue.setVue.delete 使用);
  • 无法原生监听数组,需要特殊处理。

带着 Object.defineProperty 的这几个缺点,接下来我们开始进入 Proxy 的世界。

二、🟨Proxy基本使用

下面用一段代码来演示 Proxy 的基本使用。具体代码如下:

const data = {name: 'monday',age:18
}
//const data = ['a', 'b', 'c']const proxyData = new Proxy(data, {get(target, key, receiver){//只处理本身(非原型的)属性const ownKeys = Reflect.ownKeys(target)if(oenKeys.includes(key)){console.log('get', key) //监听}const result = Reflect.get(target, key, receiver)return result // 返回结果},set(target, key, val, receiver){//重复的数据,不处理if(val === target[key]){return true}const result = Reflect.set(target, key, val, receiver)console.log('set', key, val)//console.log('result', result) //truereturn result // 是否设置成功},deleteProperty(target, key){const result = Reflect.deleteProperty(target, key)console.log('delete property', key)return result // 是否删除成功}
})

通过以上代码可得,我们先定义一个对象字面量的 data ,之后在作为 Proxy 实例化的参数进行传递。且 proxyData 实现了 getsetdeleteProperty 的方法,可以对数据进行增删改操作。

三、🟦学习Proxy语法:Reflect

我们再来认识 Proxy 的一个好朋友,Reflect

Reflect 对象有着和 Proxy 一一对应的能力,Reflect对象一共有 13 个静态方法,这也就是我们平常所听到的 proxy 有多达13种拦截行为,而 Reflect 的这13种静态方法匹配的就是 Proxy13种拦截行为

静态方法列表
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.has(obj, name)
Reflect.deleteProperty(obj, name)
Reflect.construct(target, args)
Reflect.getPrototypeOf(obj)
Reflect.setPrototypeOf(obj, newProto)
Reflect.apply(func, thisArg, args)
Reflect.defineProperty(target, propertyKey, attribute)
Reflect.getOwnPropertyDescriptor(target, propertyKey)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.ownKeys(target)

Reflect 的出现是为了替换掉 Object 上的工具函数,这里不做具体介绍,详情可查看文档 。

四、🟧Vue3如何用Proxy实现响应式

1、实现响应式

下面来实现Proxy的响应式。附上代码:

// 创建响应式
function reactive(target = {}) {if (typeof target !== 'object' || target == null) {// 不是对象或数组,则返回return target}// 代理配置const proxyConf = {get(target, key, receiver) {// 只处理本身(非原型的)属性const ownKeys = Reflect.ownKeys(target)if (ownKeys.includes(key)) {console.log('get', key) // 监听}const result = Reflect.get(target, key, receiver)// 深度监听return reactive(result)},set(target, key, val, receiver) {// 重复的数据,不处理if (val === target[key]) {return true}const ownKeys = Reflect.ownKeys(target)// 判断是已有属性还是新增属性if (ownKeys.includes(key)) {console.log('已有的 key', key)} else {console.log('新增的 key', key)} const result = Reflect.set(target, key, val, receiver)console.log('set', key, val)// console.log('result', result) // truereturn result // 是否设置成功},deleteProperty(target, key) {const result = Reflect.deleteProperty(target, key)console.log('delete property', key)// console.log('result', result) // truereturn result // 是否删除成功}}// 生成代理对象const observed = new Proxy(target, proxyConf)return observed
}// 测试数据
const data = {name: 'monday',age: 18,info: {city: 'FuZhou',a: {b: {c: {d: {e: 100}}}}}
}const proxyData = reactive(data)

我们在控制台来验证数据:

proxy

从上图中可以看到,用 proxy 来实现响应式,如果遇到需要深度递归的数组时,它不会像 defineProperty 那样深度递归,它会在什么时候 get ,什么时候再深度递归。本质上来讲就是,你获取到哪一层,那一层才会触发响应式你获取不到的深层,它就不会触发响应式。且从代码中我们可以了解到, Proxy 在修改属性时,如果数据是重复的,则不进行处理。如果数据不重复,再进行处理。这样一来,就极大程度上提高了软件的性能

2、Proxy总结

现在来对上述Proxy的内容做一个总结:

(1)深度监听,性能更好

defineProperty 是一次性递归完成;而 Proxy 是什么时候 get ,什么时候再深度递归

(2)可监听 新增/删除 属性

vue2 中, defineProperty无法新增/删除属性的,需要配合 Vue.setVue.delete 来使用,而在 Vue3 中, Proxy 可以新增和删除属性,无需进行特殊处理。

(3)可监听数组变化

vue2 中,监听数组变化是需要进行特殊处理,且只能一次性深度递归完成。而在 vue3 中,可以监听数组变化,并且是什么时候get什么时候再递归,获取不到的深层,不会触发响应式。

3、两者对比

讲到这里,我们再把 vue2 中的 Object.definePropertyvue3 中的 Proxy 做一个对比:

  • Proxy 能良好的规避 Object.defineProperty 的问题;
  • Proxy 无法兼容所有浏览器(如 IE11 ),且无法 polyfill

五、🟪结束语

从某种程度上来说, vue3Proxy 确实带来了一些好处,但同时也带来了一些问题。正因为如此, vue2Object.defineProperty 还会存在很长一段时间。所以,新技术的使用总会经过一个从试用阶段到稳定阶段的过程。

关于vue3的响应式原理讲到这里就结束啦!如有疑问或文章有误欢迎评论区留言或私信交流~

  • 关注公众号 星期一研究室 ,第一时间关注技术干货,更多有趣的专栏待你解锁~
  • 如果这篇文章对你有用,记得 一键三连 再走哦!
  • 我们下期见!🥂🥂🥂

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

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

相关文章

一名“企业定制化人才”的自诉:“我不愿意,但却无可奈何”

这是头哥侃码的第214篇原创几个月前,我曾在大智慧时期的一位同事跟我聊微信,说自己所在的公司这两年业务一直不温不火,而且从19年底就逐渐缩减技术人员。今年上半年又因为疫情的关系,公司干脆直接砍掉了剩余的三个技术部门&#x…

一文了解分而治之和动态规则算法在前端中的应用

一文了解分而治之和动态规则算法一、分而治之1、分而治之是什么?2、应用场景3、场景剖析:归并排序和快速排序二、动态规则1、动态规则是什么?2、应用场景3、场景剖析:斐波那契数列4、动态规则VS分而治之三、分而治之算法常见应用1…

leetcode1. 两数之和(两种方法)

一:题目 二:上码 1:方法一 class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {vector<int> v;for(int i 0; i < nums.size() - 1; i) {for(int j i1; j < nums.size(); j) {if(nums[i] nums[j] target) {v.push_…

排坑 | Exceptionless 5.x 无法正常发送邮件

【问题解决】| 作者 / Edison Zhou这是恰童鞋骚年的第282篇原创内容你有碰到过通过docker部署Exceptionless无法发送邮件的问题吗&#xff1f;此解决办法适用于Exceptionless 5.x版本&#xff08;如果你不想升级6.x的话&#xff09;。1问题起因去年这个时候&#xff0c;得知Exc…

一文了解贪心算法和回溯算法在前端中的应用

一文了解贪心算法和回溯算法在前端中的应用一、贪心算法1、贪心算法是什么&#xff1f;2、应用场景3、场景剖析&#xff1a;零钱兑换二、回溯算法1、回溯算法是什么&#xff1f;2、什么问题适合选用回溯算法解决&#xff1f;2、应用场景3、场景剖析&#xff1a;全排列三、贪心算…

leetcode454. 四数相加 II(思路+详解)

一:题目 二:上码 class Solution { public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {/**思路:1.我们用map容器的key值存进去前两个数的和并记录其个数,然后在后面两个数…

ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用

一文了解集合和字典在前端中的应用一、&#x1f4dd;集合1、集合是什么&#xff1f;2、前端与集合&#xff1a;使用ES6中的Set3、用Set模拟并集、交集和差集&#xff08;1&#xff09;模拟并集运算&#xff08;2&#xff09;模拟交集运算&#xff08;3&#xff09;模拟差集运算…

leetcode383. 赎金信(两种做法)

一&#xff1a;题目 二:上码 1:第一种方法 class Solution { public:bool canConstruct(string ransomNote, string magazine) {unordered_map<char,int>m,m1;for(int j 0; j < magazine.size(); j) {m[magazine[j]];}for(int i 0; i < ransomNote.size(); i) …

使用BeetleX在Linux下部署.NET多站点服务

在windows下常用IIS来部署.NET的多站点服务&#xff0c;但在Linux下就没这么方便了&#xff1b;虽然可以使用一些代理服务器如nginx&#xff0c;jexus等来反代或部署应用&#xff0c;但nginx对.NET应用的托管就相对没这么方便了&#xff0c;jexus的确是个不错的服务应用;在这里…

模块化妙用!用vue3实现一个鼠标追踪器和异步加载组件

用vue3实现一个鼠标追踪器和异步加载组件一、&#x1f5b1;️鼠标追踪器1、功能实现2、给静态页面绑定功能二、⚙️异步加载组件1、功能实现2、给静态页面绑定功能3、用泛型改造异步组件功能三、&#x1f4da;结束语周一最近学完 vue3 新特性&#xff0c;就想着用 vue3 来捣鼓…

leetcode15. 三数之和(三指针)

一:题目 二:思路 1.这里的去重是指的是我们在遍历元素的时候&#xff0c;遇到相同的挨着的相同的元素的时候要跳过 2.对元素进行排序&#xff0c;为了后面的比较 3.我们用的是三个指针&#xff0c;第一个指针i指向第一个元素&#xff0c;第二个指针left指向第二个元素,第三个指…

vue3的传送门teleport究竟有多神奇?suspense发起异步请求有多简约?

一文讲解vue3的Teleport和Suspense一、&#x1f44b;用teleport实现打开模态框操作1、teleport是什么2、实现模态框功能&#xff08;1&#xff09;设置锚点&#xff08;2&#xff09;定义子组件&#xff08;3&#xff09;定义父组件二、&#x1f91a;用Suspense1、Suspense是什…

【BCVP】实现基于 Redis 的消息队列

聆听自己的声音如果自己学不动了&#xff0c;或者感觉没有动力的时候&#xff0c;看看书&#xff0c;听听音乐&#xff0c;跑跑步&#xff0c;休息两天&#xff0c;重新出发&#xff0c;偷懒虽好&#xff0c;可不要贪杯。话说上回书我们说到了&#xff0c;Redis的使用修改《【B…

leetcode18. 四数之和(双指针)

一&#xff1a;题目 二&#xff1a;上码 class Solution { public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int> >ans;vector<int> v;sort(nums.begin(),nums.end());for(int i 0; i < nums…

过去3个多月的1200个小时里,我收获了什么?| 2021年年中总结

&#x1f55b;序言 今年三月初&#xff0c;善后了上学期事情之后&#xff0c;我开始在想&#xff0c;我的未来规划。 身边的好朋友和同学都在筹划着自己的未来&#xff0c;考研的考研&#xff0c;考公的考公。父母和老师们也在劝我说考研&#xff0c;问我考不考研。 依稀记得…

WPF 消息框 TextBox 绑定新数据时让光标和滚动条跳到最下面

WPF 消息框 TextBox 绑定新数据时让光标和滚动条跳到最下面独立观察员 2020 年 9 月 3 日我们在使用 WPF 的 TextBox 作为消息展示框时&#xff0c;如果想在出现滚动条之后&#xff0c;新消息到来时还能够被看到&#xff0c;也就是说让滚动条始终在最下面&#xff0c;或者说光标…

leedcode344. 反转字符串

一:题目 二:上码 class Solution { public:void reverseString(vector<char>& s) {//双指针for(int i 0,j s.size() - 1; i < s.size()/2; i,j--) {swap(s[i],s[j]);}} };

组件库实战 | 用vue3+ts实现全局Header和列表数据渲染ColumnList

用vue3ts实现全局Header和列表数据渲染ColumnList&#x1f5bc;️序言&#x1f4fb;一、ColumnList数据渲染1、设计稿抢先知2、数据构思3、视图数据绑定4、数据传递5、挠头情况☎️二、GlobalHeader全局Header1、设计稿抢先看2、数据构思3、视图数据绑定4、数据传递&#x1f4f…

初识ABP vNext(8):ABP特征管理

点击上方蓝字"小黑在哪里"关注我吧定义特征应用特征用户数量社交登录前言上一篇提到了ABP功能管理&#xff08;特征管理&#xff09;&#xff0c;它来自ABP的FeatureManagement模块&#xff0c;ABP官方文档貌似还没有这个模块的相关说明&#xff0c;但是个人感觉这个…

.NET Core 中导入导出Excel

操作Excel是一个比较常见的业务场景&#xff0c;本篇将使用EPPlus简单演示一个导入导出的示例。EPPlus开源地址&#xff1a;https://github.com/EPPlusSoftware/EPPlus在项目中添加EPPlus组件Install-Package EPPlus导入先准备一个Excel文件&#xff0c;将其内容读取出来&#…