在Vue3中,我们有很多与响应性相关的函数,比如toRef
、toRefs
、isRef
、unref
、shallowRef
、proxyRefs
等。在实际的开发中,合理地使用这些函数能极大地提高我们的开发效率。本文就一起来看看这些响应性相关的函数的详细用法。
ref()
对于ref
,大家并不陌生。我们经常在Vue3中使用它。它的功能是接受一个值并返回一个响应性的对象。我们可以通过.value
属性访问和修改这个值。在模板中,我们可以省略.value
。比如在下面的代码中,当按钮被点击时,页面上的count
数值将会响应式地变化。
<template>
<div>
{{ count }}
<button @click="addCount">+1</button>
</div>
</template>
<script lang='ts' setup>
import { ref } from "vue"
const count = ref(1)
const addCount = () => {
count.value++
}
</script>
toRef-- toRef(obj, key)
toRef
可以基于一个响应性对象中的属性创建一个响应性的ref
。同时,这个ref
与原始对象中的属性是同步的。如果原始对象属性的值改变了,ref
将会相应地发生变化,反之亦然。这个函数接受两个参数,一个是相应的响应,另一个是属性值,如下所示:
<template>
<div>
{{ count.a }}
{{ a }}
{{ b }}
<button @click="addCount">+1</button>
</div>
</template>
<script lang='ts' setup>
import { ref, toRef } from "vue"
const count = ref({
a: 1,
b: 2
})
const a = toRef(count.value, 'a')
const b = toRef(count.value, 'b')
const addCount = () => {
a.value++
}
</script>
当你点击按钮来修改a
的值,也就是count
中的a
也会改变。
toRefs
toRefs
可以将一个响应性的对象转换为一个普通的对象,这个普通对象的每一个属性都是一个响应性的ref
。
<template>
<div>
{{ count.a }}
{{ countAsRefs.a }}
{{ countAsRefs.b }}
<button @click="addCount">+1</button>
</div>
</template>
<script lang='ts' setup>
import { reactive, toRefs } from "vue"
const count = reactive({
a: 1,
b: 2
})
const countAsRefs = toRefs(count)
const addCount = () => {
countAsRefs.a.value++
}
</script>
在这种情况下,countAsRefs
在代码中的类型是:
{
a: Ref<number>,
b: Ref<number>
}
它的属性a
和b
都是响应性的ref
对象。同样的,他们也与原始count
对象的属性保持同步。
根据它的特征,我们通常使用它来解构一个响应性的对象,而不会失去它的响应性。
import { reactive, toRefs } from "vue";
const count = reactive({
a: 1,
b: 2,
});
const { a, b } = toRefs(count);
到这里,a
和b
都是响应性的ref
对象,并且它们与原始对象的a
和b
属性保持同步。
isRef()
从名字上看,isRef
是用来判断一个值是否为ref
。
<script lang='ts' setup>
import { reactive,ref,isRef } from "vue"
const count = ref(1);
const countObj = reactive({
a: 1,
})
console.log(isRef(count)); //true
console.log(isRef(countObj)); //false
</script>
unref()
实际上,它是一种语法糖。
val = isRef(val) ? val.value : val;
如果它是一个ref
,它就会返回它的内部值,否则它会返回它本身。这个语法糖表明它可以删除响应性对象的反应引用。举个例子,如果我们只想获得一个响应性的值,但我们并不想让它保持响应性,我们可以使用unref
来得到它的引用。例如:
<script setup lang="ts">
import { unref, ref } from "vue"
const count = ref(1)
let unRefAsCount = unref(count)
const addCount = () => {
count.value++
}
</script>
<template>
<div>
{{ unRefAsCount }}
{{ count }}
<button @click="addCount">+1</button>
</div>
</template>
代码中的unRefAsCount
没有响应性。
shallowRef
从字面上来看,它是一个浅ref
,是ref
的浅层作用形式。所谓的浅ref
就是与ref
不同,只有.value
是响应性的,而它的深层次的属性则不是响应性的。看下面的例子:
<template>
<div>
{{ shallowObj.a }}
<button @click="addCount"> +1</button>
</div>
</template>
<script lang='ts' setup>
import { shallowRef } from "vue"
const shallowObj = shallowRef({
a: 1
})
const addCount = () => {
//不触发页面更新
shallowObj.value.a++
}
</script>
然而,如果我们改变addCount
来修改整个.value
,那么它将会触发响应性。
const addCount = () => {
//不触发页面更新
//shallowObj.value.a++
let temp = shallowObj.value.a;
temp++;
shallowObj.value = {
a: temp,
};
}
triggerRef
它允许一个浅的ref
在其深度属性发生改变时强制地触发变化。举个例子,就像上面的代码示例,它无法触发反应性。
<template>
<div>
{{ shallowObj.a }}
<button @click="addCount"> +1</button>
</div>
</template>
<script lang='ts' setup>
import { shallowRef, triggerRef } from "vue"
const shallowObj = shallowRef({
a: 1
})
const addCount = () => {
shallowObj.value.a++
//添加'triggerRef'来强制改变。
triggerRef(shallowObj)
}
</script>
customRef
它是一个自定义的ref
,我们可以通过customRef
来明确地跟踪某个值的反应性的改变。这个函数接受一个函数,这个函数以track
和trigger
为参数,并且返回一个有get
和set
方法的对象。比如,封装一个自定义反应性的对象'myRef',并控制它,使得它只在值小于5的时候触发反应性。
<template>
<div>
{{ count }}
<button @click="addCount"> +1</button>
</div>
</template>
<script lang='ts' setup>
import { customRef } from "vue"
const myRef = (value: number) => {
const customValue = customRef((track, trigger) => {
return {
get() {
//通知Vue需要跟踪后续内容的变化,这个可以自由控制。
track()
return value
},
set(newValue) {
console.log(newValue);//myRef.value=xxx
// 如果newValue小于5,才触发更新
//添加一个'trigger'触发反应性,通知Vue更新页面。这里你可以自由控制是否添加'trigger'。
if(value<5) trigger()
value = newValue
}
}
})
return customValue
}
const count = myRef(0)
const addCount = () => {
count.value++
}
</script>
proxyRefs
当我们返回一个对象作为响应性引用时,对于我们想访问其属性,需要通过.value
来获取。如下面的代码,state.count
是无法获取属性值的,需要用state.value.count
来获取,如下面的例子:
<template>
<div>
{{ state.value.count }}
<button @click="addCount">+1</button>
</div>
</template>
<script lang='ts' setup>
import { ref } from "vue"
const state = ref({
count: 0
})
const addCount = () => {
state.value.count++
}
</script>
为了让响应性引用的对象可以像reactive
一样来访问和操作,Vue3推出了proxyRefs
方法。此方法可以将响应性引用的对象代理为可直接访问/操作的响应对象,如下面的代码示例中,我们可以直接通过state.count
来访问count
的值:
<template>
<div>
{{ state.count }}
<button @click="addCount">+1</button>
</div>
</template>
<script lang='ts' setup>
import { ref, proxyRefs } from "vue"
const state = ref({
count: 0
})
const stateProxy = proxyRefs(state)
const addCount = () => {
stateProxy.count++
}
</script>
来源:Shawn King
评论(0)