解构为什么可能丢失响应式?toRef / toRefs 有什么作用?
先理解原理和示例,再练习完整口述与追问。
回答要点
解构出基本值后,后续访问不再经过原对象属性;toRef / toRefs 保持与源属性的关联。解构出响应式嵌套对象的行为又不同,不能一概说所有解构都完全失效。
原理拆解
解构 reactive 的原始值属性时,执行的是一次读取:const {count}=state 得到当时数字,之后读 count 不再经过 state.count 的代理入口。解构对象属性若得到的仍是代理对象,继续修改其内部字段可能仍响应,因此不能笼统说“所有解构都完全失去响应式”。toRef 为某属性建立可联动的 ref;toRefs 批量转换当前可枚举属性。
示例与推演
import { reactive, toRefs } from 'vue'
const state = reactive({ count: 0 })
const { count } = toRefs(state)
state.count = 3
console.log(count.value) // 3
count.value = 4
console.log(state.count) // 4
读取和写入都经由关联属性,不是创建一个独立快照。props 解构还需区分编译器版本与 script setup 的转换能力。
易错点
toRefs 不会预先生成未来所有新增键的 ref。Vue3.5 等编译器支持的 props 解构行为,不应推断成普通 JavaScript 对任意 reactive 解构都可自动追踪。
参考回答可直接练习口述
响应式依靠访问被追踪的属性。把 reactive 对象的基本类型字段解构成普通变量后,读写这个变量不再经过源属性,所以不会保持关联。toRef 为一个属性创建关联 ref,toRefs 为可枚举属性创建这类 ref。若解构出的是已代理的嵌套对象,它本身的属性访问仍可能响应,不能说所有解构都完全失去响应性。
面试官可能继续问追问与完整解答展开收起
追问
Vue3.5+ 在 script setup 中的响应式 props 解构与普通对象解构为何不同?这属于编译行为还是 JS 本身?Vue3 官方响应式基础、响应式 props 解构
追问回答
Vue3.5+ 在同一 script setup 块内,编译器可以把 defineProps 解构变量的访问改写为 props 属性访问,因此具有响应式;这是编译转换,不是普通 JS 解构自动响应。向外部函数传递这类属性时,通常传 getter,如 () => foo,以保留后续读取,而不是只传当前值。