评论

收藏

[JavaScript] Vue2与Vue3的响应式区别

开发技术 开发技术 发布于:2021-12-15 16:31 | 阅读数:597 | 评论:0

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']  }}functionobserver(obj) {  if (typeof obj == 'object') {  for (let key in obj) {    defineReactive(obj, key, obj[key])  }  }}functiondefineReactive(obj, key, value) {  Object.defineProperty(obj, key, {  get() {    console.log('获取:' + key)    return value  },  set(val) {    observer(val)    console.log(key + "-数据改变了")    value = val  }  })}observer(obj)



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

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


Proxy的拦截方法
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']  }}functionobserverProxy(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的具体使用
<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的相关问题~


下期会给大家分享几种Python定时任务的方法,敬请期待~
欢迎各位关注、留言,大家的支持就是我的动力!


关注下面的标签,发现更多相似文章