响应式 API:工具
isRef()
检查一个值是否是 ref 对象。
类型
tsfunction isRef<T>(r: Ref<T> | unknown): r is Ref<T>注意返回类型是一个 类型谓词,这意味着
isRef可以作为类型守卫使用:tslet foo: unknown if (isRef(foo)) { // foo 的类型被缩小为 Ref<unknown> foo.value }
unref()
如果参数是 ref,则返回其内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val 的语法糖函数。
类型
tsfunction unref<T>(ref: T | Ref<T>): T示例
tsfunction useFoo(x: number | Ref<number>) { const unwrapped = unref(x) // 现在可以保证 unwrapped 是 number }
toRef()
可用于将值 / refs / getters 规范化为 refs(3.3+)。
也可用于为源响应式对象上的某个属性创建 ref。创建的 ref 会与其源属性同步:修改源属性会更新 ref,反之亦然。
类型
ts// 规范化签名(3.3+) function toRef<T>( value: T ): T extends () => infer R ? Readonly<Ref<R>> : T extends Ref ? T : Ref<UnwrapRef<T>> // 对象属性签名 function toRef<T extends object, K extends keyof T>( object: T, key: K, defaultValue?: T[K] ): ToRef<T[K]> type ToRef<T> = T extends Ref ? T : Ref<T>示例
规范化签名(3.3+):
js// 原样返回已存在的 refs toRef(existingRef) // 创建一个只读 ref,在访问 .value 时调用 getter toRef(() => props.foo) // 从非函数值创建普通 ref // 等同于 ref(1) toRef(1)对象属性签名:
jsconst state = reactive({ foo: 1, bar: 2 }) // 一个与原始属性同步的双向 ref const fooRef = toRef(state, 'foo') // 修改 ref 会更新原始值 fooRef.value++ console.log(state.foo) // 2 // 修改原始值也会更新 ref state.foo++ console.log(fooRef.value) // 3注意这与以下写法不同:
jsconst fooRef = ref(state.foo)上面的 ref 不会 与
state.foo同步,因为ref()接收的是一个普通数字值。当你想把 prop 的 ref 传递给组合式函数时,
toRef()很有用:vue<script setup> import { toRef } from 'vue' const props = defineProps(/* ... */) // 将 `props.foo` 转换为 ref,然后传入 // 一个组合式函数 useSomeFeature(toRef(props, 'foo')) // getter 语法 - 3.3+ 推荐 useSomeFeature(toRef(() => props.foo)) </script>当
toRef与组件 props 一起使用时,关于修改 props 的常规限制仍然适用。尝试给该 ref 赋新值等同于尝试直接修改 prop,这是不被允许的。在这种场景下,你可能需要考虑改用带有get和set的computed。更多信息请参见在组件中使用v-model指南。使用对象属性签名时,即使源属性当前不存在,
toRef()也会返回一个可用的 ref。这使得它可以处理可选属性,而这些属性不会被toRefs捕获。
toValue()
- 仅在 3.3+ 中支持
将值 / refs / getters 规范化为值。这类似于 unref(),不同之处在于它也会规范化 getters。如果参数是 getter,则会被调用并返回其返回值。
这可用于 组合式函数 中,对可以是值、ref 或 getter 的参数进行规范化。
类型
tsfunction toValue<T>(source: T | Ref<T> | (() => T)): T示例
jstoValue(1) // --> 1 toValue(ref(1)) // --> 1 toValue(() => 1) // --> 1在组合式函数中规范化参数:
tsimport type { MaybeRefOrGetter } from 'vue' function useFeature(id: MaybeRefOrGetter<number>) { watch(() => toValue(id), id => { // 响应 id 的变化 }) } // 这个组合式函数支持以下任意一种: useFeature(1) useFeature(ref(1)) useFeature(() => 1)
toRefs()
将一个响应式对象转换为普通对象,其中结果对象的每个属性都是一个 ref,指向原始对象中对应的属性。每个单独的 ref 都是使用 toRef() 创建的。
类型
tsfunction toRefs<T extends object>( object: T ): { [K in keyof T]: ToRef<T[K]> } type ToRef = T extends Ref ? T : Ref<T>示例
jsconst state = reactive({ foo: 1, bar: 2 }) const stateAsRefs = toRefs(state) /* stateAsRefs 的类型:{ foo: Ref<number>, bar: Ref<number> } */ // ref 与原始属性是“关联”的 state.foo++ console.log(stateAsRefs.foo.value) // 2 stateAsRefs.foo.value++ console.log(state.foo) // 3当你想从组合式函数返回一个响应式对象,以便消费它的组件可以对返回对象进行解构/展开而不丢失响应性时,
toRefs很有用:jsfunction useFeatureX() { const state = reactive({ foo: 1, bar: 2 }) // ...对 state 进行的逻辑操作 // 返回时转换为 refs return toRefs(state) } // 可以在不丢失响应性的情况下进行解构 const { foo, bar } = useFeatureX()toRefs只会为调用时源对象上可枚举的属性生成 refs。若要为可能尚不存在的属性创建 ref,请改用toRef。
isProxy()
检查一个对象是否是由 reactive()、readonly()、shallowReactive() 或 shallowReadonly() 创建的代理。
类型
tsfunction isProxy(value: any): boolean
isReactive()
检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。
类型
tsfunction isReactive(value: unknown): boolean
isReadonly()
检查传入的值是否为只读对象。只读对象的属性可以变化,但不能通过传入的对象直接赋值。
由 readonly() 和 shallowReadonly() 创建的代理都被视为只读对象,此外,未提供 set 函数的 computed() ref 也同样被视为只读。
类型
tsfunction isReadonly(value: unknown): boolean