最近刚学习完了 Vue3.0,V3在响应式数据的声明上不再使用原来的选项式 data 进行 retuan 返回的形式,取而代之的是通过变量修饰符使用 ref、reactive 进行手动声明的方式。相较于 Vue2.0 确实是更加灵活了许多,Vue3.0(以下简称V3)中进行响应式数据操作会使用 ref、reactive、toRef、toRefs四个核心 API 函数,那么今天就从解析以下其各个作用及其使用场景。
ref
首当其冲讲的自然是我们的 ref 函数,它的最简单使用方式如下:
<template>
<div>
<p>名字: {
{name}}</p>
<button @click="alterName">修改名字为李四</button>
</div>
</template>
<script setup>
import {ref} from "vue";
let name = ref("张三");
const alterName = () => {
name.value = "李四";
}
</script>
ref 通常用于将基本数据类型(String、Number、Boolean...)转为响应式的,也可以将引用数据类型转为响应式的、但引用数据类型我们通常会使用 reactive 进行声明。而操作 ref 声明的数据无论基本或引用数据类型都需要需要通过 .value 的方式进行(模板中不需要),那我们可以模拟看看 ref 函数的内部代码:
function ref(params){
const data = {value: params};
return new Proxy(data,{
get(){},
set(){}
})
}
也就是说,无论使用 ref 函数转的数据是什么,都会被再嵌套一层 value 属性的对象,所以我们通常使用它将基本数据类型转换为响应式的。
reactive
再看 reactive,它的最基本使用方式如下:
<template>
<div>
<p>{
{ data.name }}今年{
{data.age}}岁了</p>
<p>{
{ arr }}</p>
<button @click="alterArr">修改数组内容</button>
</div>
</template>
<script setup>
import { reactive } from "vue";
let data = reactive({
name: "张三",
age: "18"
});
let arr = reactive([1, 2, 3, 4, 5]);
const alterArr = () => {
arr.length = 0
arr.push(...[1, 1, 1, 1, 1]);
}
</script>
以上可以看到,对于修改响应式数组 arr 的整体数据时,先通过 length 设置数组长度为 0 后再去添加新内容才能继续保持响应式,而不是直接赋值,即使使用以下方式却不能保持响应式。
arr = reactive([1,1,1,1,1,]);
reactive 无法将基本数据类型转换为 响应式对象,这可能源于其内部机制,如下:
function reactive(params){
// 判断是否是 object 对象
if(params instanceof Object) return params;
return new Proxy(params, {
get(){},
set(){}
})
}
toRef
toRef可以从原来的响应式数据上拷贝一份新的响应式对象,修改新的响应式对象时也会影响到老的响应式对象,类似于浅拷贝。下面是使用场景:
<template>
<div>
<p>arr内容: {
{ arr }}</p>
<p>arrCopy内容: {
{ arrCopy }}</p>
<button @click="alterArrCopy">修改数组内容</button>
</div>
</template>
<script setup>
import {
reactive,
toRef
} from "vue";
let data = reactive({
name: "张三",
age: "18"
});
let arr = reactive([1, 2, 3, 4, 5]);
let arrCopy = toRef(arr)._object;
let objs = {arrCopy}
const alterArrCopy = () => {
objs.arrCopy[1] = "我改变了"; // == || arrCopy[1] = "我改变了"
}
</script>
或
<template>
<div>
<p>dataCopy内容: {
{ dataCopy }}</p>
<button @click="alterArrCopy">修改数组内容</button>
</div>
</template>
<script setup>
import {
reactive,
toRef
} from "vue";
let data = reactive({
name: "张三",
age: "18"
});
let dataCopy = toRef(data, "name");
let objs = {
dataCopy
}
const alterArrCopy = () => {
dataCopy.value = "我改变了";
// 或
// objs.Copy.value = "我改变了";
}
</script>
toRefs
toRefs 可以将 reactive 创建的响应式对象转换为一个个通过 .value 获取值 ref 对象, 通常可以用在 ES6 结构赋值中,当一个响应式数据属性被直接解构时,解构出来的值不会与源对象保持响应式连接,当使用 toRefs 后就可以与源数据保持响应式连接。
<template>
<div>
<p>data内容: {
{ data }}</p>
<p>{
{ name }} {
{ age }}</p>
<button @click="alterData">修改对象内容</button>
</div>
</template>
<script setup>
import {
reactive,
toRefs
} from "vue";
let data = reactive({
name: "张三",
age: "18"
});
const obj = toRefs(data);
const { name, age } = toRefs(data);
const alterData = () => {
// obj.name.value = "李四" // 和下面作用相同
name.value = "李四"; // data 的 name 属性也会发生变化
}
</script>
希望能够有所帮助!