【Vue】将响应式对象转为非响应式对象

一、使用 toRaw 函数获取原始对象

作用:获取由 reactive()ref() 创建的代理对象的原始数据副本,解除响应式追踪。 实现

import { reactive, toRaw } from 'vue';
const proxy = reactive({ name: '张三' });
const rawData = toRaw(proxy); // 获取原始对象
rawData.name = '李四'; // 修改不会触发视图更新
console.log(proxy.name); // '李四'(数据同步变化,但无响应式触发)

特点

  • 引用关系保留rawData 是原响应式对象的引用,修改会影响原对象数据,但不会触发视图更新。
  • 适用场景:序列化数据(如提交给后端)、传递到非响应式第三方库时使用。

二、通过 markRaw 永久标记非响应式

作用:标记对象或属性,使其即使被嵌套在响应式对象中也不会转换为 Proxy。 实现

import { reactive, markRaw } from 'vue';
const obj = markRaw({ price: 100 }); // 标记为非响应式
const state = reactive({
  product: obj // 嵌套后仍为非响应式
});
state.product.price = 200; // 修改有效,但不会触发响应式更新

特点

  • 深度阻断:被标记对象的所有层级属性均不会成为响应式。
  • 适用场景:静态配置数据、复杂类实例或大型列表性能优化。

三、直接解构(Vue3.4以及之前)或赋值导致响应性丢失

原理:响应式依赖通过属性访问触发追踪,直接解构或赋值会破坏引用链。 示例

const proxy = reactive({ count: 0 });
let { count } = proxy; // 解构基本类型
count++; // 不影响原对象
const localObj = proxy.obj; // 解构引用类型
localObj.name = 'test'; // 修改会影响原对象,但无响应式更新

注意

  • 深层次对象:若解构的是对象,修改其属性仍会影响原数据,但不会触发视图更新(需配合 toRawmarkRaw 彻底解除)。

四、替换整个响应式对象

场景:通过重新赋值整个对象来“重置”响应式状态。 实现

let state = reactive({ list: [] });
// 直接替换为新对象(需注意引用丢失问题)
state = { list: [1, 2, 3] }; // 新对象无响应式

局限性

  • 响应式覆盖问题:需重新调用 reactive()ref() 才能使新对象恢复响应式。

方法对比与选型建议

方法响应式影响范围数据引用关系适用场景
​​toRaw​​解除单次代理保持引用临时数据导出、避免副作用
​​markRaw​​永久阻断嵌套响应式保持引用静态数据、性能优化
​​解构/赋值​​局部属性失去响应式可能断开简单数据操作

扩展:源码视角下的响应式解除

从 Vue3 源码看,reactive() 基于 Proxy 实现,而 ref() 通过 RefImpl 包装对象。toRaw 通过访问代理对象的 __v_raw 属性获取原始数据,而 markRaw 会给对象添加 __v_skip 标记,跳过响应式转换。因此,合理使用这些 API 能精准控制响应式边界。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秀秀_heo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值