shallowRef、shallowReactive、markRaw 什么时候用?

先理解原理和示例,再练习完整口述与追问。

用于按需限制深层转换或保留第三方实例等原始对象。shallowRef 的内部对象修改通常不会触发依赖其 value 的更新,要替换 value 或使用明确的触发方式。先测成本,再决定是否采用。

深代理会为读取到的嵌套对象建立响应式处理,适合常规可变业务状态;大型不可变数据或复杂第三方实例可能不需要。shallowRef 只追踪 value 的替换,内部对象默认不深转;shallowReactive 只处理对象根层属性;markRaw 标记某个对象跳过代理。它们是在明确更新方式后减少代理成本的工具,不是通用加速开关。

js
const rows = shallowRef([{ id: 1, name: 'A' }])
rows.value[0].name = 'B' // 不因此自动触发 shallowRef
rows.value = rows.value.map(row => ({ ...row, name: 'C' }))

采用不可变数据时整体替换可触发更新;若选择 triggerRef,必须显式调用并保证调用点一致。图表实例可以按需要 markRaw,避免把它的内部结构当业务状态深追踪。

浅层与深层代理混用可能产生身份不一致和部分更新不触发。不要一边原地改内部字段,一边期待浅层容器像普通深 reactive 一样工作。

shallowRef 只追踪 value 的替换,不自动深度转换内部对象;shallowReactive 只处理根层属性;markRaw 标记对象不参与常规代理转换。它们适合大型不可变数据、编辑器实例等不适合深度观察的对象。使用前要明确哪些变化需要更新界面,否则浅层状态内部原地修改会看起来没有反应。

面试官可能继续问追问与完整解答展开收起

编辑器实例适合深度响应吗?浅层状态和深层状态混用,如何避免身份与更新行为混乱?

第三方编辑器实例通常有复杂内部结构和身份要求,可用 markRaw 或浅层容器保存。shallowRef 内部数据变更后可替换 value,或在明确需要时用 triggerRef 通知。浅层与深层混用要保持边界,避免一处拿原始对象、一处拿代理导致相等判断与更新预期不一致。