在Vue3中,存在许多与响应式相关的函数,如toRef、toRefs、isRef、unref等。巧妙地应用这些函数可以显著提升实际开发效率。本文将深入阐述这些函数的用法,以便在开发中明智地选择适当的API,并能够娴熟地回答相关问题,以满足面试官的期望。
ref()
在Vue 3中,ref 是一个用于创建响应式数据的函数。它的基本用法是通过 ref 函数创建一个包装对象,该对象具有 value 属性,任何对 value 的修改都会触发响应式更新。
<template>
<div>
<p>{{ myValue }}</p>
<button @click="updateValue">Update Value</button>
</div>
</template>
<script>
import { ref } from 'vue';
setup() {
// 在 setup 函数中使用 ref
const myValue = ref('Hello, Vue!');
// 在模板中直接使用 myValue
const updateValue = () => {
myValue.value = 'Updated Value';
};
return {
myValue,
updateValue,
};
},
};
</script>
toRef
toRef
用于创建一个指向源对象某个属性的 ref 对象。这个函数可以用于将对象的某个属性转换为响应式数据,方便在组件中使用。
下面是一个简单的示例,演示了如何使用 toRef
:
import { ref, toRef } from 'vue';
const myObject = {
firstName: 'John',
lastName: 'Doe'
};
// 使用 toRef 将对象属性转为 ref 对象
const firstNameRef = toRef(myObject, 'firstName');
// 创建一个独立的 ref
const age = ref(25);
console.log(firstNameRef.value); // 输出: John
// 修改原始对象的属性,会触发 ref 更新
myObject.firstName = 'Jane';
console.log(firstNameRef.value); // 输出: Jane
// 修改 ref 对象的值,不会影响原始对象
firstNameRef.value = 'Alice';
console.log(myObject.firstName); // 输出: Jane
在上面的例子中,toRef
接受两个参数:源对象和要转换的属性名。它返回一个 ref 对象,该对象与源对象的指定属性相绑定。这样,当源对象的属性发生变化时,通过 toRef
创建的 ref 对象也会相应地更新。
请注意,通过 toRef
创建的 ref 对象是一个独立的响应式对象,修改它的值不会影响原始对象,反之亦然。这使得在组件中更灵活地使用响应式数据。
toRefs
toRefs
用于将响应式对象的所有属性转换为 ref 对象。这个函数通常用于在 setup
函数中处理传入的 props 对象,以便在模板中能够更方便地访问和修改这些属性。
以下是一个简单的示例,演示了如何使用 toRefs
:
import { ref, reactive, toRefs } from 'vue';
const myObject = reactive({
firstName: 'John',
lastName: 'Doe'
});
// 使用 toRefs 将响应式对象的属性转为 ref 对象
const { firstName, lastName } = toRefs(myObject);
console.log(firstName.value); // 输出: John
console.log(lastName.value); // 输出: Doe
// 修改原始对象的属性,会触发 ref 更新
myObject.firstName = 'Jane';
console.log(firstName.value); // 输出: Jane
// 修改 ref 对象的值,会影响原始对象
firstName.value = 'Alice';
console.log(myObject.firstName); // 输出: Alice
在上面的例子中,toRefs
接受一个响应式对象作为参数,并返回一个包含该对象所有属性的 ref 对象集合。这样,我们可以在 setup
函数中以解构的方式获取每个属性的 ref 对象,并在模板中直接使用这些 ref 对象。
请注意,通过 toRefs
转换得到的 ref 对象与原始对象的属性之间是双向绑定的,因此修改任一方都会影响另一方。这使得在组件中更方便地处理响应式对象的属性。
isRef()
isRef
是 Vue 3 提供的一个辅助函数,用于检查一个值是否为 ref 对象。这在编程时可能是有用的,特别是当你需要确定一个值是否已经被包装成响应式对象。
以下是一个简单的示例,演示了如何使用 isRef
:
import { ref, isRef } from 'vue';
const normalValue = 'Hello, Vue!';
const myRef = ref(normalValue);
console.log(isRef(normalValue)); // 输出: false
console.log(isRef(myRef)); // 输出: true
在上面的例子中,isRef
函数接受一个值作为参数,并返回一个布尔值,指示该值是否是一个 ref 对象。如果值是 ref 对象,则返回 true
;否则,返回 false
。
这在编写逻辑时可能会有用,例如,当你需要执行不同的逻辑,具体取决于某个值是否已经被包装成 ref 对象。
unref()
unref
也是 Vue 3 提供的一个辅助函数,用于获取 ref 对象的原始值。通常,在模板中使用 ref 对象时,Vue 3 会自动解包,但在某些情况下,你可能需要显式地获取 ref 对象的原始值。
其实它就是一个语法糖
val = isRef(val) ? val.value : val;
以下是一个简单的示例,演示了如何使用 unref
:
import { ref, unref } from 'vue';
const myRef = ref('Hello, Vue!');
// 在模板中,Vue 3 会自动解包 ref 对象
console.log(myRef.value); // 输出: Hello, Vue!
// 使用 unref 获取 ref 对象的原始值
const originalValue = unref(myRef);
console.log(originalValue); // 输出: Hello, Vue!
在上面的例子中,unref
函数接受一个参数,该参数可以是任何值,但通常是一个 ref 对象。如果参数是 ref 对象,则 unref
返回 ref 对象的原始值,否则返回参数本身。
在大多数情况下,你不需要显式使用 unref
,因为在模板中,Vue 3 会自动解包 ref 对象。但在一些特殊的编程场景中,可能需要使用 unref
来确保获取到的是原始值。
shallowRef
shallowRef
用于创建一个 ref 对象,但与普通的 ref
不同,shallowRef
会对对象进行浅层的响应式处理。这意味着只有对象的第一层属性会变成响应式,而嵌套对象内部的属性不会成为响应式。
以下是一个简单的示例,演示了如何使用 shallowRef
:
<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 = () => {
let temp = shallowObj.value.a;
temp++;
shallowObj.value = {
a: temp,
};
};
triggerRef
它可以让浅层的 ref 即 shallowRef 深层属性发生改变的时候强制触发更改,比如上面触发不了响应式的代码示例加入triggerRef
后
<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
customRef
是 Vue 3 提供的一个函数,用于创建一个自定义的 ref 对象。通过 customRef
,你可以定义自己的获取器和设置器来实现对 ref 对象的完全自定义控制。
以下是一个简单的示例,演示了如何使用 customRef
:
import { customRef } from 'vue';
// 创建一个自定义的 ref 对象
const myCustomRef = customRef((track, trigger) => {
let value = 'Hello, Vue!';
return {
get() {
// 告诉 Vue 哪些依赖被追踪
track();
return value;
},
set(newValue) {
// 更新值,并触发更新
value = newValue;
trigger();
}
};
});
console.log(myCustomRef.value); // 输出: Hello, Vue!
myCustomRef.value = 'Updated Value';
console.log(myCustomRef.value); // 输出: Updated Value
在上面的例子中,customRef
接受一个工厂函数作为参数,该函数返回一个对象,包含 get
和 set
方法。get
方法用于获取值,并告诉 Vue 哪些依赖被追踪,而 set
方法用于更新值,并触发相应的更新。
customRef
的使用场景通常是在需要执行一些自定义逻辑来管理 ref 对象时,例如延迟加载、缓存或者与外部系统集成。这使得你能够在 ref 对象的读取和写入时执行额外的操作。
总结
-
ref(): 接收一个值并返回一个响应式的对象,可以使用.value 属性来访问和修改这个值。
-
toRef(obj, key): 根据一个响应式对象中的一个属性,创建一个响应式的 ref,并且该 ref 和原对象中的属性保持同步。 -toRefs(obj): 将一个响应式对象转换成一个普通对象,其中普通对象的每个属性都是响应式的 ref。
-
isRef(value): 判断某个值是否是 ref 对象。
-
unref(value): 用于解除响应式引用
-
shallowRef(value): 创建一个浅层的 ref,只有 value 属性是响应式的,深层的属性不具备响应式。
-
triggerRef(ref): 强制浅层的 ref 发生改变时触发响应式。
-
customRef(factory): 自定义 ref 对象,可以显式地追踪某个值的响应式变化。
、