Vue2与Vue3的响应式【代理对象:Proxy 反射对象:Reflect的实例学习】

一. Vue2与Vue3的响应式

1.1 Proxy和Reflect

Proxy:Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

Reflect:Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler (en-US)的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。

1.2 案例体验(代理对象:Proxy 反射对象:Reflect)

新建一个html文件:01_响应式对象.html

在js代码里:建立User对象:

const user= {
    
    
    name:"上进小菜猪",
    age:21,
    wife:{
    
    
        name:"小猪",
        age:22
    }
}

代理对象:代理对象里有get和set方法:

const proxyUser = new Proxy(user,{
    
    
    get(target,prop){
    
    
        console.log("get方法调用了")
        return Reflect.get(target,prop)
    },
    set(target,prop,val){
    
    
        console.log("set方法调用了")
        return Reflect.set(target,prop,val)
    },
    deleteProperty(){
    
    
    }
})

输出测试:

console.log(proxyUser.name)
proxyUser.name="小猪"
console.log(user)

效果展示:

image-20230319124114345

1.3 Vue2与Vue3的响应式区别

Vue2和Vue3在响应式系统上有很大的不同。下面是一些主要的区别:

1.数据劫持方式不同:

在Vue2中,它使用的是 Object.defineProperty 来劫持对象属性的读取和赋值,从而实现响应式。而在Vue3中,它使用的是 ES6 的 Proxy 对象来实现数据劫持。相比于Vue2,Vue3使用Proxy能够更好的支持嵌套对象和动态增加属性等。

2.Vue3中的Reactivity API

Vue3引入了新的Reactivity API,包括 refreactive 等新的API,使得响应式系统更加灵活和易用。ref用于对单个值进行响应式处理,reactive用于对对象进行响应式处理。

3.Composition API的影响

Vue3中引入了Composition API,它可以让我们更好的组织代码逻辑,而这也意味着Vue3中的响应式系统是基于Composition API进行设计的。因此,在Vue3中使用Composition API会更加方便和直观,而在Vue2中,使用选项式API则更为适用。

4.Vue3中的缓存机制

在Vue3中,响应式系统引入了新的缓存机制,通过缓存可以避免重复的计算,从而提高性能。

总的来说,Vue3的响应式系统相比Vue2更加灵活和高效,并且可以更好地与Composition API进行集成。

二.总结

2.1 vue2的响应式

  • 核心:
    • 对象: 通过defineProperty对对象的已有属性值的读取和修改进行劫持(监视/拦截)
    • 数组: 通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持
Object.defineProperty(data, 'count', {
    
    
    get () {
    
    }, 
    set () {
    
    }
})
  • 问题
    • 对象直接新添加的属性或删除已有属性, 界面不会自动更新
    • 直接通过下标替换元素或更新length, 界面不会自动更新 arr[1] = {}

2.2 Vue3的响应式

核心:

  • 通过Proxy(代理): 拦截对data任意属性的任意(13种)操作, 包括属性值的读写, 属性的添加, 属性的删除等…
  • 通过 Reflect(反射): 动态对被代理对象的相应属性进行特定的操作
new Proxy(data, {
    
    
	// 拦截读取属性值
    get (target, prop) {
    
    
    	return Reflect.get(target, prop)
    },
    // 拦截设置属性值或添加新属性
    set (target, prop, value) {
    
    
    	return Reflect.set(target, prop, value)
    },
    // 拦截删除属性
    deleteProperty (target, prop) {
    
    
    	return Reflect.deleteProperty(target, prop)
    }
})

proxy.name = 'tom'   
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Proxy 与 Reflect</title>
</head>
<body>
  <script>
    
    const user = {
      
      
      name: "John",
      age: 12
    };

    /* 
    proxyUser是代理对象, user是被代理对象
    后面所有的操作都是通过代理对象来操作被代理对象内部属性
    */
    const proxyUser = new Proxy(user, {
      
      

      get(target, prop) {
      
      
        console.log('劫持get()', prop)
        return Reflect.get(target, prop)
      },

      set(target, prop, val) {
      
      
        console.log('劫持set()', prop, val)
        return Reflect.set(target, prop, val); // (2)
      },

      deleteProperty (target, prop) {
      
      
        console.log('劫持delete属性', prop)
        return Reflect.deleteProperty(target, prop)
      }
    });
    // 读取属性值
    console.log(proxyUser===user)
    console.log(proxyUser.name, proxyUser.age)
    // 设置属性值
    proxyUser.name = 'bob'
    proxyUser.age = 13
    console.log(user)
    // 添加属性
    proxyUser.sex = '男'
    console.log(user)
    // 删除属性
    delete proxyUser.sex
    console.log(user)
  </script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_52908342/article/details/129649393