| 对比项 | ref |
unref |
|---|---|---|
| 目的 | 创建响应式引用 | 读取响应式引用的值 |
| 输入 | 任意值(如 5, "text") |
任意值(可能是 ref/computed/普通值) |
| 输出 | Ref<T> 对象(带 .value) |
T(原始值) |
| 是否响应式 | ✅ 是 | ❌ 否(只是读取) |
| 典型用途 | 在组件中声明响应式状态 | 在工具函数中安全处理不确定类型的参数 |
ref
定义:
ref 是一个函数,用于将一个普通值(primitive value)包装成一个响应式的“引用对象”(Reactive Reference)。
import { ref } from 'vue'
const count = ref(0)
// count 现在是一个对象:{ value: 0 }
console.log(count.value) // 0
count.value = 1 // 修改值
console.log(count.value) // 1
为什么需要 ref
ref 让原始值也能参与 Vue 的响应式系统。
- Vue 的响应式系统基于 JavaScript Proxy,而 Proxy 只能代理对象。
- 像
number、string、boolean这些原始类型(primitive)无法被 Proxy 直接追踪。 - 所以 Vue 用
ref把它们“装进一个对象里”({ value: ... }),从而实现响应式。
unref
定义:
unref 是一个工具函数,用于“安全地获取值”:如果参数是 ref 或 computed,返回它的 .value;否则直接返回原值。
import { ref, computed, unref } from 'vue'
const a = ref(10)
const b = computed(() => a.value * 2)
const c = "hello"
console.log(unref(a)) // 10 (等价于 a.value)
console.log(unref(b)) // 20 (等价于 b.value)
console.log(unref(c)) // "hello" (普通值直接返回)
为什么需要 unref?
在编写通用函数或组合式函数(composables) 时,你可能不确定传入的参数是:
- 一个普通值(如
"px") - 还是一个
ref(如ref("px")) - 或一个
computed(如computed(() => "44px"))
unref 让你不用关心类型,统一安全地取出值。
// ❌ 危险:如果传入的是 ref,会出错
function setPadding(el, padding) {
el.style.padding = padding + 'px' // 如果 padding 是 ref,变成 "[object Object]px"
}
// ✅ 安全:用 unref
function setPadding(el, padding) {
el.style.padding = unref(padding) + 'px'
}
// 调用方式更灵活:
setPadding(el, 10) // 普通数字
setPadding(el, ref(10)) // ref
setPadding(el, computed(() => 10)) // computed
unref 返回值的类型
unref(x) 的返回类型 = x 如果是普通值,则返回 x 的类型;如果 x 是 Ref<T> 或 ComputedRef<T>,则返回 T。
当传入普通值(非响应式)
返回类型 = 输入类型
const str = "hello"
const num = 42
const obj = { name: "Alice" }
// unref 直接返回原值,类型不变
const a = unref(str) // type: string
const b = unref(num) // type: number
const c = unref(obj) // type: { name: string }
当传入 Ref<T>
返回类型 = T(即 .value 的类型)
import { ref } from 'vue'
const count = ref(10) // Ref<number>
const title = ref("Hello") // Ref<string>
const user = ref({ id: 1 }) // Ref<{ id: number }>
const a = unref(count) // type: number
const b = unref(title) // type: string
const c = unref(user) // type: { id: number }
当传入 ComputedRef<T>
import { computed } from 'vue'
const double = computed(() => 5 * 2) // ComputedRef<number>
const fullName = computed(() => "张三") // ComputedRef<string>
const a = unref(double) // type: number
const b = unref(fullName) // type: string