标准答案
- shallowRef 只追踪 .value 的替换,不会深度追踪 value 内部对象属性变化,适合大对象、外部实例或手动整体替换的状态。
- shallowReactive 只让对象第一层属性响应式,嵌套对象不会继续转成深层响应式。
- markRaw 会标记一个对象不被 Vue 转成响应式代理,适合图表实例、编辑器实例、地图实例等第三方对象。
- 这些 API 不是性能优化的默认选项,只有在深层响应式成本高、代理会破坏实例行为或确实只关心引用变化时才使用。
- 使用浅层响应式后,内部字段变更不会自动触发视图更新,需要通过整体替换、triggerRef 或其它明确方式通知更新。
题目解析
这道题的重点是响应式深度,而不是把这些 API 统一说成“性能优化”。
普通业务表单、简单对象和组件状态一般不需要 shallow 或 markRaw,默认 ref/reactive 更直观。
第三方库实例被 Proxy 包裹后可能出现身份判断、私有字段或方法绑定问题,markRaw 可以避免这类风险。
代码示例
下面展示了用 shallowRef 保存大对象引用,以及用 markRaw 保存第三方实例。
TypeScript
const chartOptions = shallowRef(createLargeOptions())
function updateOptions() {
chartOptions.value = createLargeOptions()
}TypeScript
const chart = shallowRef<Chart | null>(null)
onMounted(() => {
chart.value = markRaw(new Chart(canvasRef.value))
})常见误区
- 把 shallowRef 当成普通 ref 使用,修改内部字段后疑惑页面为什么不更新。
- 为了所谓性能到处使用 markRaw,导致响应式链路断开且问题难排查。
- 不知道第三方实例可以跳过响应式代理,反而把实例塞进 deep reactive 对象里。