在 Vue 3 中,有多种方法和工具可以将参数变为响应式或处理响应式数据。
一、将参数变为响应式的方法
-
reactive:
- 将一个普通对象转换为响应式对象。
javascript">import { reactive } from 'vue'; const state = reactive({ count: 0 });
-
readonly:
- 创建一个只读的响应式对象。
javascript">import { readonly } from 'vue'; const state = readonly({ count: 0 });
-
ref:
- 创建一个包含单个响应式值的对象。
javascript">import { ref } from 'vue'; const count = ref(0);
-
shallowReactive:
- 创建一个浅层响应式对象,仅对对象的顶层属性进行响应式处理。
javascript">import { shallowReactive } from 'vue'; const state = shallowReactive({ count: 0 });
-
shallowReadonly:
- 创建一个浅层只读的响应式对象,仅对对象的顶层属性进行只读处理。
javascript">import { shallowReadonly } from 'vue'; const state = shallowReadonly({ count: 0 });
-
shallowRef:
- 创建一个浅层响应式引用,仅对引用的顶层属性进行响应式处理。
javascript">import { shallowRef } from 'vue'; const count = shallowRef(0);
-
toRef 和 toRefs:
toRef
:将对象的某个属性转换为一个响应式的ref
对象。toRefs
:将对象的所有属性转换为响应式的ref
对象。
javascript">import { reactive, toRef, toRefs } from 'vue'; const state = reactive({ count: 0 }); const countRef = toRef(state, 'count'); const stateRefs = toRefs(state);
-
computed:
- 创建一个计算属性,它会根据其依赖项自动更新。
javascript">import { reactive, computed } from 'vue'; const state = reactive({ count: 0 }); const doubleCount = computed(() => state.count * 2);
-
watch 和 watchEffect:
watch
:监听响应式数据的变化,并在变化时执行回调函数。watchEffect
:立即执行传入的函数,并在其依赖的响应式数据变化时重新执行。
javascript">import { reactive, watch, watchEffect } from 'vue'; const state = reactive({ count: 0 });watch(() => state.count, (newValue, oldValue) => {console.log(`count changed from ${oldValue} to ${newValue}`); });watchEffect(() => {console.log(`count is now ${state.count}`); });
-
customRef:
- 创建一个自定义的
ref
,可以自定义其依赖跟踪和触发更新的方式。
javascript">import { customRef } from 'vue';function useDebouncedRef(value, delay = 200) {let timeout;return customRef((track, trigger) => {return {get() {track();return value;},set(newValue) {clearTimeout(timeout);timeout = setTimeout(() => {value = newValue;trigger();}, delay);}};}); }const debouncedRef = useDebouncedRef(0);
- 创建一个自定义的
-
markRaw:
- 将一个对象标记为不可响应的,这样 Vue 就不会将它转换为响应式对象。
javascript">import { reactive, markRaw } from 'vue'; const rawObject = markRaw({ foo: 'bar' }); const state = reactive({ raw: rawObject });
-
triggerRef:
- 手动触发由
ref
创建的响应式对象的更新。
javascript">import { ref, triggerRef } from 'vue'; const myRef = ref({ foo: 'bar' });// 更新 ref 的值 myRef.value.foo = 'baz';// 手动触发更新 triggerRef(myRef);
- 手动触发由
这些工具和方法提供了灵活多样的方式来管理和处理响应式数据,帮助开发者根据不同的需求实现响应式状态管理。
二、使用 toRef 和 toRefs 的场景
toRef
和 toRefs
在某些特定情况下仍然有其独特的用途和优势。让我解释一下为什么以及何时使用 toRef
和 toRefs
。
使用 toRef
和 toRefs
的场景
-
解构对象时保持响应式:
当你需要解构一个响应式对象时,直接解构会丢失响应性。toRefs
可以帮助你在解构时保持响应性。javascript">import { reactive, toRefs } from 'vue';const state = reactive({ count: 0, name: 'Vue' });// 直接解构会丢失响应性 // const { count, name } = state;// 使用 toRefs 保持响应性 const { count, name } = toRefs(state);
-
单独引用对象属性:
如果你需要单独引用对象的某个属性并传递给其他组件或函数,可以使用toRef
。javascript">import { reactive, toRef } from 'vue';const state = reactive({ count: 0 });// 使用 toRef 创建单独的响应式引用 const countRef = toRef(state, 'count');// 现在 countRef 是一个 ref,可以单独传递
示例解释
javascript">import { reactive, toRef, toRefs } from 'vue';const state = reactive({ count: 0 });// 使用 toRef 将 state 对象的 count 属性转换为一个 ref
const countRef = toRef(state, 'count');// 使用 toRefs 将 state 对象的所有属性转换为 refs
const stateRefs = toRefs(state);
在这个示例中:
state
是一个响应式对象,它的所有属性都是响应式的。toRef(state, 'count')
将state
对象的count
属性转换为一个ref
,这样你可以单独使用countRef
,并且它仍然是响应式的。toRefs(state)
将state
对象的所有属性转换为ref
,这样你可以解构stateRefs
,并且每个属性仍然是响应式的。