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

Vue2和Vue3响应式的区别

数据响应式是什么?

​所谓 数据响应式 就是建立 响应式数据依赖(调用了响应式数据的操作)之间的关系,当响应式数据发生变化时,可以通知那些使用了这些响应式数据的依赖操作进行相关更新操作,可以是DOM更新,也可以是执行一些回调函数。

Vue2 和 Vue3 响应式的区别

从Vue2 到 Vue3 都使用了响应式,那么它们之间有什么区别?

  • Vue2响应式:基于Object.defineProperty()实现的。
  • Vue3响应式:基于Proxy()实现的。

为什么Vue3会选择Proxy()替代defineProperty()?看下面两个例子:

Vue2响应式

// Vue2响应式声明
defineReactive(data,key,val){Object.defineProperty(data,key,{enumerable:true,configurable:true,get:function(){console.log(`对象属性:${key}访问defineReactive的get!`)return val;},set:function(newVal){if(val===newVal){return;}val = newVal;console.log(`对象属性:${key}访问defineReactive的set!`)}})
}

Vue2定义对象:

let obj = {};
this.defineReactive(obj,'name','sapper');// 修改obj的name属性
obj.name = '小明';
console.log('obj',obj.name);// 为obj添加age属性
obj.age = 18;
console.log('obj',obj);
console.log('obj.age',obj.age);// 为obj添加数组属性
obj.hobby = ['游戏', '原神'];
obj.hobby[0] = '王者';
console.log('obj.hobby',obj.hobby);// 为obj添加对象属性
obj.student = {school:'大学'};
obj.student.school = '学院';
console.log('obj.student.school',obj.student.school);

在这里插入图片描述

​ 从上图可以看出,使用defineProperty()定义了包含name属性的对象obj,然后添加age属性、添加hobby属性(数组)、添加student属性(对象),并分别访问,都没有触发obj对象中的get、set方法。也就是说defineProperty()定义对象不能监听添加额外属性或修改额外添加的属性的变化,再看这样一个例子:

let obj = {};
// 初始化就添加hobby
this.defineReactive(obj,'hobby',['游戏', '原神']);
// 改变数组下标0的值
obj.hobby[0] = '王者';
console.log('obj.hobby',obj.hobby);

在这里插入图片描述

​ 假设一开始就为obj添加hobby属性,发现修改数组下标0的值,并没有触发obj里的set方法,也就是说defineProperty()定义对象不能监听根据自身数组下标修改数组元素的变化,注意,如果是直接用defineProperty()定义数组元素是可以监听的,但是对于数组比较大的时候就很牺牲性能,尤其考虑到性能就没有使用这种方法。

Vue3响应式

看一下Proxy代理的对象例子:

// proxy实现
let targetProxy = {name:'sapper'};
let objProxy = new Proxy(targetProxy,{get(target,key){console.log(`对象属性:${key}访问Proxy的get!`)return target[key];},set(target,key,newVal){if(target[key]===newVal){return;}console.log(`对象属性:${key}访问Proxy的set!`)target[key]=newVal;return target[key];}
})

对象应用:

// 修改objProxy的name属性
objProxy.name = '工兵';
console.log('objProxy.name',objProxy.name);// 为objProxy添加age属性
objProxy.age = 12;
console.log('objProxy.age',objProxy.age);// 为objProxy添加hobby属性
objProxy.hobby = ['游戏', '原神'];
objProxy.hobby[0] = '王者';
console.log('objProxy.hobby',objProxy.hobby);// 为objProxy添加对象属性
objProxy.student = {school:'大学'};
objProxy.student.school = '学院';
console.log('objProxy.student.school',objProxy.student.school);

在这里插入图片描述

​ 从上图可以发现Proxy与defineProperty的明显区别之处,Proxy能支持对象添加或修改触发get、set方法,不管对象内部有什么属性

defineProperty

Object.defineProperty()

  • defineProperty() 定义对象不能监听添加额外属性修改额外添加的属性的变化;
  • defineProperty() 定义对象不能监听根据自身数组下标修改数组元素的变化。

Vue里的用法例子:

 data() {return {name: 'sapper',student: {name: 'sapper',hobby: ['原神', '天涯明月刀'],},};},methods: {deleteName() {delete this.student.name;console.log('删除了name', this.student);},updateArr() {this.student.hobby[0] = '王者';console.log('更新了this.student的hobby', this.student);},addItem() {this.student.age = 21;console.log('添加了this.student的属性', this.student);}
}

在这里插入图片描述

上图中确实可以修改data里的属性,但是页面不能及时渲染,所以Vue2提供了两个属性方法解决了这个问题:Vue.$setVue.$delete

注意不能直接this._ data.age这样去添加age属性,也是不支持的。

this.$delete(this.student, 'name');  // 删除student对象属性name
this.$set(this.student.hobby, 0, '王者');  // 更新student对象属性hobby数组
this.$set(this.student, 'age', '21');  // 添加student对象属性age

在这里插入图片描述

上图中可以修改data里的属性,并且页面能够及时渲染。

proxy

Proxy:解决了上面两个弊端,proxy可以实现:

  • 可以直接监听对象而非对象属性,可以监听对象添加额外属性的变化;
const user = {name:'张三'}
const obj = new Proxy(user,{get:function (target,key){console.log("get run");return target[key];},set:function (target,key,val){console.log("set run");target[key]=val;return true;}
})
obj.age = 22;
console.log(obj); // 监听对象添加额外属性打印 set run!  
  • 可以直接监听数组的变化
const obj = new Proxy([2,1],{get:function (target,key){console.log("get run");return target[key];},set:function (target,key,val){console.log("set run");target[key]=val;return true;}
})
obj[0] = 3;
console.log(obj); // 监听到了数组元素的变化打印 set run!  
  • Proxy 返回的是一个新对象,而 Object.defineProperty() 只能遍历对象属性直接修改。

  • 支持多达13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等,是Object.defineProperty() 不具备的。

总的来说,Vue3响应式使用Proxy解决了Vue2的响应式的诟病,从原理上说,它们所做的事情都是一样的,依赖收集依赖更新

http://www.lryc.cn/news/25765.html

相关文章:

  • 模型实战(6)之Alex实现图像分类:模型原理+训练+预测(详细教程!)
  • 【大数据】最全的大数据Hadoop|Yarn|Spark|Flink|Hive技术书籍分享/下载链接,持续更新中...
  • RIG Exploit Kit 仍然通过 IE 感染企业用户
  • GIS在地质灾害危险性评估与灾后重建中的实践技术应用及python机器学习灾害易发性评价模型建立与优化进阶
  • SQL SERVER中SCHEMA的詳解
  • 【LeetCode】剑指 Offer(13)
  • 帮助小型企业实现业务增长的7种数字营销策略
  • 互联网行业的高级产品经理和普通产品经理有哪些区别?
  • aardio - 【库】简单信息框
  • 程序员必备!最值得收藏的宝藏网站大盘点
  • Android 10.0 Settings 关掉开发者模式
  • 软件测试面试必杀篇:【2023软件测试面试八股文宝典】
  • 原子级操作快速自制modbus协议
  • 大数据之Apache Doris_亚秒级响应_大数据处理分析_介绍_概述---大数据之Apache Doris工作笔记0001
  • SpringCloud学习笔记 - 分布式系统全局事务管理 - Seata1.5.2+Nacos+OpenFeign
  • LeetCode190_190. 颠倒二进制位
  • atomic 原子操作
  • DataGear 制作基于Vue前端框架渲染的数据可视化看板
  • JavaFX Scene Builder 下载安装
  • dva( 轻量级的应用框架 )
  • 数据结构:堆的实现与建堆时间复杂度分析
  • 对“车辆销售配置器”的认识与理解
  • Linux编译器——gcc/g++(预处理、编译、汇编、链接)
  • Java 操作图片进行缩放旋转翻转加水印
  • 不能去演唱会现场就多听听耳机里的他们,教你用python来实现一个音乐播放器
  • CLion Debug 调试 Makefile 构建的 C 语言程序断点不起作用
  • ·神经网络
  • 【Java 多线程学习】
  • 【计算机考研408】快速排序的趟数问题 + PAT 甲级 7-2 The Second Run of Quicksort
  • CSS-Grid(网格)布局