markRaw的核心价值是让特定数据跳过响应式代理,避免深度递归处理以降低渲染耗时;它需在数据进入响应式系统前标记,适用于超大树形结构、长静态列表等只读大数据场景。

在 Vue 3 组件渲染性能分析中,markRaw 的核心价值是让特定数据跳过响应式代理过程,从而避免初始化阶段的深度递归处理,直接降低渲染耗时。它不是用于运行时“关闭”响应式,而是在数据进入响应式系统前就切断代理路径。
什么时候该用 markRaw 做渲染性能优化
当组件首次挂载或数据更新时出现明显卡顿,尤其是以下情况:
- 渲染超大树形结构(如万级节点的选择器、组织架构图)
- 长列表展示静态配置(如 1000+ 条地区、字典、权限菜单)
- 组件接收了体积大、嵌套深但完全只读的数据源(如接口返回的完整表单配置 JSON)
- 使用虚拟滚动但仍感觉初始化慢——问题可能出在数据代理阶段,而非渲染阶段
怎么正确加 markRaw 才真正生效
关键在于标记时机必须早于 reactive 或 ref 赋值,否则代理已发生,markRaw 就无效了:
- ❌ 错误写法:先赋值再标记 →
const data = ref({}); data.value = apiRes; data.value = markRaw(data.value);(此时代理已完成) - ✅ 正确写法:标记后再进响应式容器 →
const data = ref(markRaw(apiRes));或const state = reactive({ tree: markRaw(apiRes) }); - ✅ 接口层直接标记 →
const res = await fetchTree(); treeData.value = markRaw(res);
配合数据清洗效果更明显
markRaw 单独使用能跳过代理,但如果原始数据含大量冗余字段(如日志时间戳、调试 flag、未用的 metadata),仍会增加内存和序列化开销。建议组合使用:
审查 Vue 管理后台的变更请求(Vue 2 + Element UI,Vue 3 + Element Plus)。重点关注最小化变更实现、上线风险检查以及回归检查清单生成。
立即学习“前端免费学习笔记(深入)”;
- 先用轻量函数提取必要字段(如只保留
id、name、children) - 再对清洗后的结果调用
markRaw - 示例:
treeData.value = markRaw(formatTree(res));
验证是否真的跳过代理
可在控制台快速确认:
console.log(isReactive(treeData.value)); // falseconsole.log(isReactive(treeData.value.children[0])); // false(嵌套也不代理)- 检查对象上是否存在
__v_skip: true属性(不可枚举,需用Object.getOwnPropertyDescriptors查看)
不复杂但容易忽略:markRaw 不是性能“开关”,而是数据契约——你明确告诉 Vue “这个数据永远不会变,别管它”。用对了,树渲染从 184ms 降到 17ms 就很真实。


















