toRef能保留默认值并实现响应式同步,因为它建立属性引用通道而非快照取值;解构后用ref会丢失响应式,而toRef在属性不存在时返回undefined且后续赋值自动同步。

直接用 ref 解构 reactive 对象的属性,会丢失响应式连接,也拿不到原始默认值;真正能保留默认值 + 响应式同步的,是 toRef —— 它不是复制值,而是建立指向原属性的“引用通道”。
toRef 能守住默认值的关键逻辑
当你调用 toRef(obj, 'name') 时:
- 如果
obj.name当前有值(比如'Alice'),返回的 ref 的.value就是这个值,且与obj.name双向联动 - 如果
obj.name还不存在或为undefined,toRef仍返回一个合法 ref,.value初始为undefined,后续obj.name = 'Bob'会立刻反映到该 ref 上 - 它不依赖初始赋值,而是动态绑定属性路径,所以“默认值”本质由源对象决定,
toRef忠实镜像它
对比 ref():为什么 ref() 会丢默认值
ref(obj.name) 是一次快照式取值:
- 执行时读取
obj.name的当前值(比如'Alice'),然后创建一个独立 ref - 之后
obj.name改成'Bob',这个 ref 完全无感,因为它和obj没有关联 - 若
obj.name初始为undefined,ref(obj.name)就得到ref(undefined),后续属性新增也不会更新
正确写法:用 toRef 提取单个带默认值的属性
假设你有一个 reactive 对象,部分字段可能延迟初始化:
const user = reactive({
id: 1001,
name: 'Tom',
// email 尚未设置
})
安全提取并保持响应式:
-
const nameRef = toRef(user, 'name')→nameRef.value === 'Tom',改它等于改user.name -
const emailRef = toRef(user, 'email')→emailRef.value === undefined,但一旦user.email = 't@x.com',emailRef.value立刻变成't@x.com' - 模板中直接用
{{ nameRef.value }}或{{ emailRef.value || '暂无邮箱' }},无需额外 watch 或判断
常见误操作及修复
❌ 错误:解构后用 ref 包一层
const { name } = user // 普通字符串,已失响应性
const nameRef = ref(name) // 快照,不再同步 user.name
✅ 正确:跳过解构,直接 toRef
const nameRef = toRef(user, 'name') // 始终绑定 user.name
⚠️ 注意:不要对 toRef 返回的 ref 再做 ref() 包裹,否则又断开连接。


















