Vue2与Vue3的数据响应式区别

Vue2与Vue3的数据响应式区别使用过 vue2 的小伙伴们都知道,Vue 初始化实例时会把 data 中声明的对象属性进行 getter/setter 转化,也就是使用了 Object.defineProperty() 这个方法,把这个对象属性变成响应式的。

欢迎大家来到IT世界,在知识的湖畔探索吧!

Vue2与Vue3的数据响应式区别

使用过 vue2 的小伙伴们都知道,Vue 初始化实例时会把 data 中声明的对象属性进行 getter/setter 转化,也就是使用了 Object.defineProperty() 这个方法,把这个对象属性变成响应式的。如果在该对象上新增一个属性,不会触发该对象的响应,这时就要通过用 $set()、$forceUpdate() 之类的方法触发响应。特别是数据量大,需要检测的属性较多时,感觉就很笨重,每一次数据更新都能感觉到明显的卡顿,很不友好。

所以 vue3 毫不犹豫的把数据响应的方式给换成了 Proxy ,喜大普奔!公司的新项目也迅速地换上了 vue3 ,在学习过程中,记录一下 vue2 和 vue3 的数据响应式区别。

Vue2 响应式数据原理

Vue2 的数据响应使用了 ES5 中的 Object.defineProperty(obj, prop, descriptor)。

Object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历。如果,属性值是对象,还需要深度遍历。

优点:

  • 兼容性好,支持 IE9。

缺点:

  • 只能劫持对象的属性(key值.Object.key()),因此需要对每个对象的每个属性进行遍历。
  • 无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。是通过重写数据的操作方法(push、unshift…)来对数组进行监听的。
  • 不能对 es6 新产生的 Map,Set 这些数据结构做出监听。

模拟vue2中用Object.defineProperty(obj, prop, descriptor)实现的数据响应

let obj = { key:'cue' flags: { name: ['AAA', 'VVV', 'FFF'] } } function observer(obj) { if (typeof obj == 'object') { for (let key in obj) { defineReactive(obj, key, obj[key]) } } } function defineReactive(obj, key, value) { Object.defineProperty(obj, key, { get() { console.log('获取:' + key) return value }, set(val) { observer(val) console.log(key + "-数据改变了") value = val } }) } observer(obj)

欢迎大家来到IT世界,在知识的湖畔探索吧!

Vue3 响应式数据原理

vue3的数据响应使用了 ES6 中的新增特性 Proxy。

Proxy,翻译过来的意思是“代理”,用在这里表示由它来“代理”某些操作,让我们能够以简洁易懂的方式控制外部对对象的访问。其功能类似于设计模式中的代理模式。可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

简而言之,Proxy 可以劫持整个对象,并返回一个新的对象。

优点:

  • 可以直接监听对象而非属性;
  • 可以直接监听数组的变化;
  • 有多种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等是Object.defineProperty 不具备的;
  • 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改。

Proxy的拦截方法

欢迎大家来到IT世界,在知识的湖畔探索吧!get(target, propKey, receiver) set(target, propKey, value, receiver) has(target, propKey) deleteProperty(target, propKey) ownKeys(target) getOwnPropertyDescriptor(target, propKey) defineProperty(target, propKey, propDesc) preventExtensions(target) getPrototypeOf(target) isExtensible(target) setPrototypeOf(target, proto) apply(target, object, args) construct(target, args)

模拟vue3中用Proxy实现的数据响应

let obj = { key:'cue' flags: { name: ['AAA', 'VVV', 'FFF'] } } function observerProxy(obj) { const handler = { get(target, key, receiver) { console.log("获取:" + key); if (typeof target[key] === "object" && target[key] !== null) { // 如果是对象,就添加 proxy 拦截 return new Proxy(target[key], handler); } return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { console.log("设置:" + key); return Reflect.set(target, key, value, receiver); }, }; return new Proxy(obj, handler); } let newObj = observerProxy(obj); 

vue3在开发中的一些具体使用

欢迎大家来到IT世界,在知识的湖畔探索吧!<scriptlang="ts">import { defineComponent, setup } from'vue'exportdefault defineComponent({ setup(props, context) { //props父组件传的值 //在setup()里我们不能用this //vue2.0里的 this.$emit, this.$psrent, this.$refs在这里都不能用了。 //context就是对这些参数的集合 //context.attrs //context.slots //context.parent 相当于2.0里 this.$psrent //context.root 相当于2.0里 this //context.emit 相当于2.0里 this.$emit //context.refs 相当于2.0里 this.$refs let data = reactive({ message: "hello world" }); //响应式对象 let message = ref("hello world"); //响应式字符串 let arr = ref(['hello','world']); //响应式数组字符串 let username = computed(() => user.firstname + " " + user.lastname); //计算属性 const copy = readonly(original); //只读代理 ... } }) </script>

总结

vue2 和 vue3 两个版本用起来相差还是蛮大的,从原理、写法上都不太一样,所以旧项目的操作上,无法直接升级到 vue3。目前公司旧项目用 vue2、新项目用 vue3,在了解基本的数据响应原理后,维护不同版本 vue 开发的项目,也更得心应手。

刚接触 vue 的小伙伴,建议从 vue2 开始学起,再学习 vue3,可以深刻体会到“取其精华,去其糟粕”这个道理。

下期会给大家分享几种Python定时任务的方法,敬请期待~

欢迎各位关注、留言,大家的支持就是我的动力!

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/79110.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信