Vue3响应式:ref vs reactive
ref
简单介绍一下使用方式
<template>
<p>{{ name }}</p>
<el-button @click="obtain">改变这个参数</el-button>
</template>
<script setup>
import { ref } from 'vue';
// 可以做基本类型和对象类型的响应式
const age = ref(18);
const obtain = ()=>{
// 直接输出
console.log(age.value)
// 改变这个值
age.value = 20
}
</script>
reactive
<template>
<p>{{ people.name }}</p>
<el-button @click="obtain">改变这个参数</el-button>
</template>
<script setup>
import { reactive } from 'vue';
// 只能做对象类型的响应式
const people = reactive({name:'小明'});
const obtain = ()=>{
// 直接输出
console.log(people.name)
// 改变这个值
people.name = '小红'
}
</script>
对比
在简单了解了reactive和ref的使用之后,现在,不管是想要实现对象还是基本数据类型的响应式转换,都可以轻松做到了
但是!!!是否和我一样产生了几个疑问?
为什么ref创建的值获取后面要加上 .value
为什么reactive只能做对象的响应式
他们两个我们具体要使用哪个
带着这些疑问去学习这个东西
为什么ref可以做基本类型的响应式 并且后面需要加上 .value
我们了解 Proxy的都知他只能监听对象,而无法直接处理原始数据类型的数据。考虑到这一点,我们是不是可以尝试将原始数据放置在对象中,以便Proxy进行监听呢
function ref(value) {
// 将传入的初始值存在reactiveObj中
const reactiveObj = { value };
// 返回一个Proxy代理
return new Proxy(reactiveObj, {
// 读取数据
get(target) {
console.log('获取');
return target.value;
},
// 更新数据
set(target, property, value, ) {
target.value = value
console.log('更新');
return 'set';
},
});
}
// 测试
const count = ref(100000);
count.value // 输出'get'
count.value = 1; // 输出'set'
在这个ref的封装过程中,我们将值包装在一个对象的value属性中,这个过程就解释了为什么我们需要使用.value来访问和修改ref封装返回的值
同样,这里不管传入的数据是对象类型还是基本数据类型,都会经过这个函数包装将其放在一个对象里,然后再使用Proxy监听包装后的对象,所以才让ref具备同时代理原始数据和对象数据的能力。
为什么reactive只能做对象的响应式
// 定义一个对象
let testObj = {
name: '11'
};
// 将对象传入Proxy中,并传入处理器对象来重写它的get和set方法
const proxyObj = new Proxy(testObj, {
get: () => {
// 获取数据的时候输出‘get’
console.log('get');
},
set: () => {
// 设置数据的时候输出‘set’
console.log("set");
return 'set';
}
});
// 实验数据是否正常被监听了
proxyObj.name
proxyObj.name = '22';
// 因为reactive使用 Proxy 来实现数据劫持的。只要了解了`Proxy`的特性,就能明白为什么`reactive`不支持原始数据类型了
// 如果是基本类型就会报错: Cannot create proxy with a non-object as target or handler
现在了解需要使用ref还是reactive了吗?
以上仅个人理解,欢迎大家补充👏