Vue3的响应式原理

139 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

喜欢就点个赞吧🎈😊

🎉 前言

这里我们来比较一下Vue 和Vue3的响应式数据的原理。在Vue2中使用的是Object.defineProperty.而在Vue3中使用的是Proxy代理的方式。一下我们将对这两者之间进行比较。

🎉 Vue2的数据劫持的弊端

这是由于Object.defineProperty这是提供了两个方法一个是个get,另一个是set。只有当获取或者修改的时候才可以进行数据的劫持。

  • 新增属性、删除属性页面不会发生变化。

解决方法使用组件中的$set(对象,属性名,属性值)进行设置或者直接用Vue.set();使用组件中的$delete(属性名,属性值)进行设置或者直接用Vue.delete();

  • 直接通过下标修改数组,界面也不会发生变化。

解决方法:使用组件中的$set(对象,属性名,属性值)进行设置或者直接用Vue.set();使用组件中的$delete(属性名,属性值)进行设置或者直接用Vue.delete();或者通过调用Vue二次封装的数组的方法。splice()来进行下标值得替换。

//Vue2的响应式原理
let person = {
name:'张三',
age = 10
}
let p = {}
Object.defineProperty(p, 'name',{
configurable:true  //可删除的
enumerable: true//可枚举的
writable:true//可修改的
get(){
return person.name
}
set(value){}
person.name = value
})

🎉 Vue3的响应式原理

🎇 window.Proxy内置的构造函数

image.png

🎇Vue3中的实现方式

  • 通过Proxy (代理)︰拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等。
  • 通过Reflect(反射)︰对源对象的属性进行操作。

image.png

🎉 Vue3中的reactive和ref

🎇 定义方面

  1. ref用来定义:基本类型数据。
  2. reactive用来定义:对象(或数组)类型数据。
  3. 备注: ref也可以用来定义对象(或数组)类型数据,它内部会自动通过 reactive转为代理对象。

🎇 原理方面

  1. ref通过object.defineProperty()的get与set来实现响应式(数据劫持)。
  2. reactive通过使用Proxy来实现响应式(数据劫持)﹐并通过Reflect操作源对象内部的数据。

🎇 使用方面

  1. ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value
  2. reactive定义的数据:操作数据与读取数据:均不需要.value。

🎉 Vue3中的setup

在Vue3中, 要将所有的东西写到setup(){}中。


export default {
  name: 'App',
  // setup返回一个对象,则对象的属性方法在模板上均有体现
  setup() {
    //响应式数据
    //在vue3中使用ref 使用会生成一个RefImpl引用实例对象,实现的方法也是 Object.defineProperty
    let name = ref('张三')
    let person = reactive({
      name: "李四",
      age: 20,
      hobbies: ['抽烟', '喝酒', '烫头']
    })
    //方法
    function sayHello() {
      alert(`${name}这是我的名字 `)
    }

    function sayName() {
      alert(person.name)
    }
    return {
      name,
      sayHello,
      person,
      sayName
    }

  }
}

🎇 注意点

  • 在beforeCreate之前执行一次,this是undefined。
  • setup的参数
    • props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。
    • context: 上下文对象
      • attrs:值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性,this.$attrs
      • slots: 收到的插槽内容,相当于this.$slots 。
      • emit:分发自定义事件的函数,相当于|this.$emit]。