在 Vue 3 中,props 属性不可直接解构以保持响应性,须用 toRef(props, 'key') 创建响应式 ref;toRef 仅支持顶层 key,未声明字段返回 undefined,嵌套属性需先解构,且转换后 ref 为只读。

在 Vue 3 中,父组件通过 props 向子组件传递响应式数据时,直接解构或赋值会导致失去响应性。比如 const name = props.name 得到的是一个普通值,后续父组件更新 name,子组件里的 name 不会同步变化。这时用 toRef 就能解决——它把 props 的某个属性“连通”为独立的 ref,保持双向响应。
为什么 props 属性不能直接解构?
props 是只读代理(readonly),且其属性本身不是 ref 类型。直接解构会切断与源数据的响应链接:
-
const { name } = props→name是快照值,不响应父组件更新 -
const name = props.name→ 同样是静态读取,无法触发视图更新 - 即使父组件传的是
ref或reactive,子组件也必须用toRef显式桥接才能安全使用
toRef 转换 props 单个属性的正确写法
在 setup 中,对 props 的具体字段调用 toRef(props, 'fieldName'):
- 第一个参数是
props对象(来自defineProps) - 第二个参数是字符串形式的属性名(必须是 props 中已声明的 key)
- 返回值是一个
Ref,可参与计算属性、监听器、模板插值等所有 ref 场景
import { defineProps, toRef, watch } from 'vue'<br>const props = defineProps({ title: String, count: Number })<br>const titleRef = toRef(props, 'title')<br>const countRef = toRef(props, 'count')<br>// 可用于 watch<br>watch(titleRef, (newVal) => console.log('title changed:', newVal))<br>// 模板中直接写 {{ titleRef }},无需 .value
常见误用与注意事项
toRef 不是万能胶,用错场景反而引入 bug:
- 不要对未声明的 props 字段使用,如
toRef(props, 'xxx')但xxx不在defineProps类型定义里 → 运行时返回undefined的 ref - 避免对嵌套属性直接使用,例如
toRef(props, 'user.name')❌ ——toRef只支持顶层 key,深层需先解构对象再处理 - 如果需要多个字段,优先考虑
toRefs(props)批量转换,比一个个写更简洁安全 - 转换后的 ref 仍是只读的(因为 props 本身只读),尝试赋值
titleRef.value = 'new'会静默失败或报 warning


















