ref适用于所有类型,必须用.value访问;reactive仅支持对象/数组,直接属性访问;基本类型必须用ref,复杂结构推荐reactive。
Vue 中的 ref 本身不区分“Ref 数组”或“Ref 对象”这种说法——它统一包装任意值,但数组和对象在使用方式、响应行为和实际注意事项上确实有明显差异。关键不在 ref 类型,而在于你用 ref 包什么、怎么改、怎么读。
ref 可以安全包装数组,比如 const list = ref([1, 2, 3])。它能响应式,但要注意:
list.value(例如 list.value.length 或 list.value[0])push()、pop()、splice()、sort() 等——这些会触发视图更新list.value = [4, 5, 6]),虽然有效,但会丢失原有响应式连接;更稳妥的是用 list.value.splice(0, list.value.length, ...newArray)
map、filter、slice 这类返回新数组的方法直接更新,因为它们不改原数组,Vue 捕捉不到变化ref 也能包装对象,例如 const user = ref({ name: 'Alice', age: 30 }),但它和 reactive 的体验不同:
user.value.name,不能直接 user.name(否则报错或读不到)user.value.profile.address.city),每次读写都要带一长串 .value,容易出错也难维护reactive
ref 的设计初衷不是为了替代 reactive,而是解决基本类型无法响应的问题。所以判断依据很实在:
立即学习“前端免费学习笔记(深入)”;
loading = ref(false)、searchTerm = ref(''))→ 必用 refdata = ref(null),后续 data.value = await api.get())→ 用 ref 更自然v-model 配合的输入框、开关等 → ref 是标准做法reactive 确实更适合数组和结构化对象,但它有硬性限制:
reactive(42) 会警告且无效)const { count } = reactive({ count: 0 }) → count 不再响应){{ state.user.profile.name }})而 ref 没这些限制:它能包一切,解构安全(const { value: count } = ref(0) 仍可用),模板中自动解包({{ count }}),还天然适配组合式 API 的参数传递场景。