Vue3 中的 markRaw 和toRaw和shallowRef
文章类型:Vue
发布者:hp
发布时间:2025-04-25
在vue3中,增加很多API,那么markRaw 、toRaw、shallowRef他们的使用场景是什么呢?
1:作用=>显式标记对象为「非响应式」,使其永远不会被 Vue 转换为响应式代理对象
2:原理=>通过添加 __v_skip 内部属性跳过代理转换流程
3:场景=>
防止第三方库实例(如 ECharts、Three.js)被代理引发冲突
优化静态数据(如大列表)性能,避免代理开销
动态组件切换时避免组件实例被代理
1:作用=>返回由 reactive 或 ref 创建的响应式对象的原始对象,绕过代理直接操作数据
2:原理=>通过递归查找响应式对象的原始引用实现解包
3:场景=>
需要临时修改响应式对象的原始数据且不触发视图更新
与第三方库交互时需传递原始数据而非代理对象
1:作用=>创建仅跟踪 .value 引用变化的响应式对象,不深度追踪内部属性变化
2:原理=>仅在 .value 被替换时触发更新,内部属性修改无响应
3:场景=>
处理大型对象或数组时避免深度响应式转换的性能损耗
动态组件切换时存储组件实例
1:markRaw
import { reactive, markRaw } from 'vue';
const thirdPartyObj = markRaw({ data: [...] }); // 标记为非响应式
const state = reactive({
config: thirdPartyObj // 嵌套在响应式对象中仍保持原始状态
});
2:toRaw
import { reactive, toRaw } from 'vue';
const proxy = reactive({ data: 1 });
const raw = toRaw(proxy); // 获取原始对象
raw.data = 2; // 修改不会触发视图更新
3:shallowRef
import { shallowRef } from 'vue';
const largeObj = shallowRef({ list: [...] });
largeObj.value.list.push(1); // 内部修改不触发更新
largeObj.value = { list: [...] }; // 替换整个对象触发更新
1:markRaw=>标记后的对象不可逆,无法通过 reactive 或 ref 恢复响应式。仅标记当前对象,嵌套属性仍可能被代理(需逐层标记)
2:toRaw=>仅对响应式对象有效,普通对象调用返回自身。修改原始对象可能导致与代理对象数据不一致,(谨慎操作)
3:shallowRef=>使用 .value 赋值新对象时才触发更新,内部属性修改需手动调用 triggerRef()