markraw 是 vue 3 中用于显式标记对象跳过响应式转换的工具函数,被标记对象不会被 reactive、ref 或嵌套代理,适用于第三方类实例、大型静态数据、dom/canvas 对象等场景。

markRaw 是 Vue 3 提供的一个工具函数,用于**显式标记一个对象,使其完全跳过响应式转换过程**。被 markRaw 包裹的对象,即使传入 reactive、ref(内部值为对象时)或作为响应式对象的属性嵌套,Vue 都不会对其建立 getter/setter,也不会递归代理其子属性。
什么时候该用 markRaw?
典型场景包括:
React 与 Next.js 性能优化指南,源自 Vercel 工程团队。适用于编写、审查或重构 React/Next.js 代码时使用。
- 第三方库的类实例(如 Map、Set、Date、RegExp、自定义类),它们自身已有内部状态和方法,响应式代理反而会破坏行为或引发错误
- 大型不可变数据结构(如渲染用的静态配置、JSON Schema),不需要响应式开销
- 需要与原生 DOM 元素、Canvas 上下文、WebGL 对象等直接交互的对象
- 避免循环引用导致的代理死锁或内存泄漏
基本用法:直接标记后再传入 reactive
✅ 正确示例:
```jsimport { reactive, markRaw } from 'vue'
// 创建一个普通对象
const plainObj = { name: 'Alice', age: 30 }
// 用 markRaw 包裹,再传给 reactive
const rawObj = markRaw(plainObj)
const state = reactive({
user: rawObj // ✅ user 不会被转为响应式,保持原始对象行为
})
console.log(isReactive(state.user)) // false
console.log(isProxy(state.user)) // false
```
常见误区与注意事项
- markRaw 必须在 reactive/ref 创建前调用:不能对已响应式的对象再用 markRaw“撤回”,它只在创建阶段起作用
-
markRaw 返回的是原对象本身(非副本),只是打了个内部标记(
__v_skip: true),不改变对象结构 -
嵌套在响应式对象中仍有效:即使放在
reactive({ foo: markRaw(obj) })里,obj 依然不会被代理 -
对 ref 的影响:如果
ref(markRaw(obj)),则ref.value是原始对象;但注意ref本身仍是响应式包装器(可被 .value 访问/赋值),只是其内部值不被代理
配合 isRaw 判断是否被标记
可用 isRaw() 辅助调试:
import { markRaw, isRaw } from 'vue'
const obj = {}
console.log(isRaw(obj)) // false
console.log(isRaw(markRaw(obj))) // true
```










