Vue 3 非响应式逃生舱:markRaw、toRaw 与 shallow 系列的正确分工
test12026-11-011 次阅读
响应式不是免费的
Vue 的 reactive 会把对象递归地包成 Proxy。问题是:遇到第三方实例(图表、编辑器)、超大数组、或者你根本不想追踪变化的对象,深度代理既浪费性能也可能让第三方库出错。Vue 提供了一组“逃生舱”:markRaw、toRaw、shallowRef、shallowReactive。关键不是会不会用,而是分清各自的分工。
markRaw:告诉 Vue 别代理这个对象
echarts、monaco、mapbox 这类库返回的是自带内部状态的实例,一旦被 reactive 递归包裹就会报错或卡顿。用 markRaw 包一层,Vue 就不会去代理它。
import { markRaw, onMounted, ref } from 'vue'
import * as echarts from 'echarts'
const el = ref(null)
let chart
onMounted(() => {
// 关键:markRaw 防止 echarts 实例被变成响应式 Proxy
chart = markRaw(echarts.init(el.value))
chart.setOption({ /* ... */ })
})
shallowRef:只追踪引用替换
当你要替换的是一整个大列表,而不是逐个改元素,用 shallowRef 只监听 .value 的重新赋值,跳过深层比对,渲染更快。
import { shallowRef } from 'vue'
const list = shallowRef([])
// 必须整体替换引用才会触发更新
async function load() {
const data = await fetchBigList()
list.value = data
}
toRaw:临时拿回原始对象
在需要把响应式对象直接交给第三方库(比如传给表单校验器、序列化)时,用 toRaw 拿到没有被 Proxy 包裹的原始引用,避免库读到奇怪的代理字段。
import { reactive, toRaw } from 'vue'
const form = reactive({ name: '张三', age: 20 })
const plain = toRaw(form) // 普通对象,不含 Proxy 开销
// 传给只认普通对象的旧库
legacyValidate(plain)
怎么选
- 第三方实例、不该被追踪的对象:markRaw。
- 大对象只换不改、追求更新速度:shallowRef / shallowReactive。
- 临时绕过响应式、把数据交出去:toRaw。
记住一条:响应式是为了让 UI 跟着变,不是为了追着每一个字节。分不清边界,才会写出又慢又怪的代码。
T
test1
文章作者
响应式不是免费的 Vue 的 reactive 会把对象递归地包成 Proxy。问题是:遇到第三方实例(图表、编辑器)...
- 分类
- 技术
- 发布时间
- 2026-11-01
- 字数
- 约 1204 字
- 阅读
- 1 次
