前言
Vue3从发布到现在,相信大家已经开始学习&&使用了吧,看到响应性 API -> Refs模块的时候是不是觉得:Wa ,这都是什么,好多API长得还很相似。什么ref , unref, toRef, toRefs, isRef......
本文主要介绍toRef和toRefs的用法以及其他响应性 API的扩展,希望对大家有所帮助。
菜鸡认知,如有错误欢迎指正。
正文
toRef和toRefs都是响应性 API,但是在使用上却有很大的不同,本文将带你一起探索
说他们之前 我们先来看一看这两个API
ref
- 接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value 属性,指向该内部值。
- 如果将对象分配为 ref 值,则它将被 reactive 函数处理为深层的响应式对象。
- 常用于简单数据类型,也可以用于对象。
reactive
- 当将 ref 分配给 reactive property 时,ref 将被自动解包。
- reactive 将解包所有深层的 refs,同时维持 ref 的响应性。
- 响应式转换是“深层”的——它影响所有嵌套属性。
- 常用于复杂数据类型
toRef和toRefs用法
toRef
可以用来为源响应式对象上的某个 property 新创建一个
ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。
- 把响应式对象/普通对象的某一个属性变为
Ref对象 - 需要传递两个参数,第一个参数是哪个对象,第二个参数是对象里面的属性
请看下方代码:
<script>
import { reactive, toRef } from "vue";
export default {
setup(props) {
const state = reactive({
age: 18,
name: "zs"
});
const ageRef = toRef(state, "age");
console.log(ageRef.value) // 18
ageRef.value++
console.log(ageRef.value) // 19
console.log(state.age) // 19
const nameRef = toRef(state, "name");
const emptyRef = toRef(state, "empty");
return {
ageRef,
nameRef,
emptyRef,
};
},
};
</script>
上方代码将源对象中的age转换为了ref对象ageRef,对ageRef进行修改发现源对象中的age也跟随着修改
toRef只能把某一个属性变化为ref对象
有同学会想到:
“如果对象里面有100个参数 需要变化为ref对象,我要难道要写100次吗?”
这个时候toRefs就派上用场了
toRefs
将响应式对象转换为普通对象,普通对象的每个属性都是
ref对象。只会为源对象中包含的 属性 生成 ref。如果要为特定的 property 创建 ref,则应当使用
toRef
<script>
import { reactive, toRefs } from "vue";
export default {
setup(props) {
const state = reactive({
age: 18,
name: "zs"
});
const stateToRefs = toRefs(state)
console.log(stateToRefs.age.value) // 18
stateToRefs.age.value++
console.log(stateToRefs.age.value) // 19
console.log(state.age) // 19
return {
...stateToRefs
};
},
};
</script>
可以看出, toRefs大大的减少了代码量,还可以通过解构赋值返回响应式对象,真的是yyds!
小明:“源对象里面如果再包含一个对象他还会是响应式的吗?“
我们将上方的state加一个family的对象,然后对family里面的属性操作看一看会是什么样的情况
<template>
<div>age---{{ family.age }}</div>
<button @click="family.age++">年龄+1</button>
</template>
<script>
import { reactive, toRefs } from "vue";
export default {
setup(props) {
const state = reactive({
age: 18,
name: "zs",
family:{
shaikh:'毛里求斯',
age:188
}
});
const stateToRefs = toRefs(state)
return {
...stateToRefs
};
},
};
</script>
上方例子看到:包含了对象仍然是响应式,我们再来看看对象里面包含数组的响应式例子 state改造如下
const state = reactive({
age: 18,
name: "zs",
family:{
shaikh:'毛里求斯',
age:188,
member:[
{
age:2,
id:'1',
name:'宝宝'
},
{
id:'2',
age:55,
name:'爸爸'
},
{
id:'3',
age:55,
name:'妈妈'
}
]
}
});
视图层改变如下:
<template>
<div>酋长的年龄---{{ family.age }}</div>
<h3>家庭成员</h3>
<div v-for="item in family.member" :key="item.id">
宝宝的年龄:{{ item.age }}
宝宝的名字:{{ item.name }}
<button @click="item.age++">{{ item.name }}年龄+1</button>
</div>
</template>
可以看出依然是可以响应式的 toRefs是引用赋值
拓展(引用赋值)
- 使用‘=’,他只拷贝数据在内存中的地址,应为基本数据类型是存放在 栈 中所以赋值的时候会重新在内存中创建,而引用类型则只会拷贝地址指针
- 引用赋值:将一个变量的数据地址,“拷贝”一份,传给另了另一个变量。这两个变量,指向“同一个地址”。大家共享同一份数据。如果其中一个变量的值发生了改变,那么,另一个变量的值也得变。要变一起变。
源响应式对象
上方有个词 源响应式对象,这是什么?有同学会有一些困惑。我个人理解的就是:我们需要操作的ref对象,对哪个对象操作 哪个就是源对象。
小节
toRef
- 当对象中不存在某个属性时会创建该属性,如果要为特定的 property (属性)创建 ref,则应当使用 toRef
- 需要传递两个参数,第一个参数是哪个对象,第二个参数是对象里面的属性
- 把响应式对象/普通对象的某一个属性变为
Ref对象
toRefs
- toRefs只会为源对象中存在的属性变为
Ref对象 。如果要为特定的 property (属性)创建 ref,则应当使用 toRef - toRefs是引用赋值
- 把响应式对象的所有属性变为
Ref对象,可以在不丢失响应性的情况下对返回的对象进行解构/展开
共同点
- 都是响应式
拓展
unref
如果参数是一个 ref,则返回.value的值,否则返回参数的值。这是 val = isRef(val) ? val.value : val 的语法糖函数。
const add = ref('+1')
unref(add) // '+1'
const add = '+1'
unref(add) // '+1'
isRef
检查值是否为一个 ref 对象。