toRefs用于批量解构已知结构的reactive对象并返回含多个ref的普通对象,toRef用于安全提取单个可能不存在的属性并返回ref;二者均复用源响应式连接,不新建响应式系统。
直接解构 reactive 对象会让属性变成普通值,失去响应性——改它不会更新原对象,也不会触发视图刷新。要让解构后的变量仍与源对象保持双向同步,就得用 toRef 或 toRefs 建立引用通道,而不是复制值。
当你有一组关联的响应式字段(比如表单状态、用户信息),又希望在模板或逻辑中自由使用各字段名(如 {{ name }}、{{ email }}),toRefs 是最自然的选择。
reactive 对象的所有第一层可枚举属性,逐个转成独立的 ref
name.value 或在 <script setup> 中直接赋新值(如 name = 'Vue')都会同步到源对象示例:
import { reactive, toRefs } from 'vue'const form = reactive({name: '',email: '',isActive: true})const { name, email, isActive } = toRefs(form) // ✅ 安全解构// 修改会同步到 form.namename.value = 'Alice'// 或在 <script setup> 中(自动解包):// name = 'Alice'
当你只关心响应式对象中的某个字段,或者该字段可能暂时不存在(比如可选的 prop、异步加载后才有的嵌套属性),toRef 更轻量、更健壮。
ref
state.foo 当前是 undefined,toRef(state, 'foo') 依然返回有效 ref,后续赋值也会同步到源对象示例:
const props = defineProps({user: Object,title: String // 可选})// 即使 title 未传入,也能安全创建 refconst titleRef = toRef(props, 'title')// 模板中可直接用 {{ title }}(自动解包),且响应式有效
ref(value) 是创建一个全新的响应式值,和任何现有对象无关;而 toRef(obj, key) 是“借用”已有响应式对象里的某个属性,建立实时链接。
const nameRef = ref(state.name) → 只读取一次初始值,后续 state.name 变了,nameRef.value 不会变,反之亦然const nameRef = toRef(state, 'name') → nameRef.value 和 state.name 始终保持一致user.profile.avatar),toRefs 不生效,得用 toRef(user, 'profile') 再配合 toRef(profile, 'avatar'),或改用计算属性多数场景下,优先用 toRefs 处理整体对象;对个别动态字段、可选字段或需要透传给子组件的单一属性,用 toRef 更精准。两者都返回标准 ref,可直接参与 watch、computed 或传入其他组合式函数。