Vue3的响应式

101 阅读2分钟

实现原理

  1. 通过Proxy(代理)拦截对象中任意属性的变化,包括:属性值的读改、属性的添加、属性的删除等
  2. 通过Reflect(反射)对源对象的属性进行操作
const obj = new Proxy(originObj, {
    // target为源对象,prop为属性
    // 拦截读取属性值
    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)
    }
})

Vue3处理响应式数据的函数

ref函数

ref函数用于定义响应式数据,创建了一个包含响应式数据的引用对象(reference对象,简称ref对象)
当接收的值为基本类型数据时,响应式依靠Object.defineProperty()中的getset实现。

import { ref } from 'vue'
// ...
const xxx = ref(initValue)

// JS操作数据
xxx.value = newValue

// 模板中读取数据
<div>{{xxx}}</div>

当接收的值为对象类型数据时,内部求助了vue3的reactive函数。

const obj = ref({
    a:'',
    b:''
})

// JS操作数据
obj.value.a = newValue

// 模板中读取数据
<div>{{obj.a}}</div>

reactive函数

reactive函数接收对象,返回一个代理对象(Proxy的实例对象,简称proxy对象)

import { reactiv } from 'vue'
//...
// const 代理对象 = reactive(源对象)
const person = reactive({
    name: 'zs',
    age: 18,
    job: {
        type: '前端'
    },
    hobby: ['学习', '打球']
})

// 修改数据不需要.value
function changePerson(){
    person.name
    person.age
    person.job.type
    person.hobby[0]
}
return {
    person
}

reactive函数定义的响应式数据是深层次的,内部基于ES6的Proxy实现,通过代理对象操作源对象内部数据,且该操作可以被vue监测到。

reactive和ref对比

  1. 从定义数据类型来说:ref用来定义基本类型数据,reactive用来定义对象(或数组)类型数据;ref也可以用来定义对象或数组类型数据,它内部会自动通过reactive转为代理对象
  2. 从原理角度来说:ref通过Object.defineProperty()getset来实现响应式(数据劫持);reactive通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据
  3. 从使用的角度来说:ref定义的数据操作需要.value,模板读取数据时不需要.valuereactive定义的数据操作和读取都不需要.value