实现原理
- 通过Proxy(代理)拦截对象中任意属性的变化,包括:属性值的读改、属性的添加、属性的删除等
- 通过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()中的get和set实现。
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对比
- 从定义数据类型来说:
ref用来定义基本类型数据,reactive用来定义对象(或数组)类型数据;ref也可以用来定义对象或数组类型数据,它内部会自动通过reactive转为代理对象 - 从原理角度来说:
ref通过Object.defineProperty()的get和set来实现响应式(数据劫持);reactive通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据 - 从使用的角度来说:
ref定义的数据操作需要.value,模板读取数据时不需要.value;reactive定义的数据操作和读取都不需要.value