markRaw用于标记非响应式对象以跳过Proxy代理,适用于确定不变且无需视图更新的第三方实例、大型只读数据、静态组件定义等;必须在进入reactive或ref前调用,仅作用于目标对象本身,不递归,不可用于基础类型。

直接用 markRaw 包裹不需要响应式追踪的对象,就能跳过 Vue 的 Proxy 代理过程,避免递归遍历、减少内存占用和不必要的更新触发——这不是让数据“变快”,而是让它“不被劫持”。
哪些数据适合 markRaw?
核心判断标准只有一条:这个对象你确定它不会变,也不需要视图随它变化而更新。
- 第三方库实例(如 ECharts 实例、Leaflet 地图对象、WebGL 渲染器)
- 大型只读数据(如初始化后固定的树形配置、国家地区列表、mock 表格数据)
- 静态组件定义(比如
中预设的组件对象) - 外部传入且不参与响应式逻辑的对象(如插件注入的结构化数据、服务端直出的配置)
怎么写才真正生效?
markRaw 必须在对象进入响应式系统之前调用。一旦被 reactive 或 ref 处理过,再标记就无效了。
- ✅ 正确:先
markRaw(new Chart(dom)),再放进reactive({ chart: ... }) - ✅ 正确:对整个大数组或嵌套对象整体标记,例如
markRaw(fetchTreeData()) - ❌ 错误:先
reactive(obj),再markRaw(reactiveObj)—— 它已经是代理对象了
容易忽略的关键细节
markRaw 的作用范围有限,不是“一劳永逸”的开关。
- 它只影响目标对象本身,不递归处理内部属性;若内部引用了
ref或reactive对象,那些部分仍会响应 - 只能用于对象、数组、函数等引用类型,对字符串、数字等基础类型无效
- 标记后无法用
toRaw还原——因为它压根没被代理过 - 配合
provide/inject更稳妥:在 provide 阶段就标记,防止下游组件无意中把它塞进自己的 reactive 里
别误用:markRaw 不是万能优化符
如果一个对象本该响应式更新(比如你在模板里用 {{ config.title }},还希望 title 改变时视图重绘),却给它加了 markRaw,那更新就失效了。
- 业务状态数据(用户输入、表单值、开关状态)——不要 markRaw
- 需要依赖收集、触发 computed 或 watch 的字段——不要 markRaw
- 不确定是否变化、或未来可能扩展响应逻辑的数据——暂不标记
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











