本文深入解析 Vue 3 响应式工具函数 toRefs、toRaw 与 readonly 的核心原理与实战用法,涵盖解构响应式对象、绕过代理访问原始数据及冻结响...
快速概述
在 Vue 3 中,toRefs、toRaw 与 readonly 是三个极为实用的响应式工具函数,它们分别解决响应式对象解构丢失、访问原始非代理数据以及创建只读响应式副本的核心问题。适用场景包括:组合式函数返回响应式状态、性能敏感操作中绕过 Proxy 开销、以及跨组件传递不可变数据。前置环境要求为 Vue 3.2+,且需从 vue 包中显式导入这些函数。
核心概念与原理
Vue 3 的响应式系统基于 Proxy 实现,reactive() 返回的代理对象在读写时触发依赖收集与更新。然而,直接解构响应式对象会丢失响应性——因为解构得到的是原始值的拷贝。此时 toRefs 将响应式对象转换为普通对象,其中每个属性都是一个 ref,保持与源对象的双向同步。toRaw 则返回 reactive 或 readonly 代理背后的原始对象,用于临时读取数据而不触发响应式追踪。readonly 创建一个只读代理,任何修改操作都会在开发模式下触发警告,适用于传递不可变数据。
实战步骤与代码
步骤 1:使用 toRefs 安全解构
import { reactive, toRefs } from 'vue';
const state = reactive({ count: 0, name: 'Vue' }); // 解构后每个属性仍是响应式 ref const { count, name } = toRefs(state);
count.value++; // 修改 ref 会同步到 state.count console.log(state.count); // 输出 1
步骤 2:用 toRaw 访问原始对象
import { reactive, toRaw } from 'vue';
const original = { count: 0 }; const state = reactive(original); const raw = toRaw(state);
console.log(raw === original); // true,绕过代理直接操作 raw.count++; // 不触发响应式更新
步骤 3:readonly 冻结响应性
import { reactive, readonly } from 'vue';
const state = reactive({ count: 0 }); const frozen = readonly(state);
frozen.count = 1; // 开发模式警告,修改无效 state.count = 2; // 源对象仍可修改,frozen 同步更新
常见坑点与优化
- toRefs 仅处理顶层属性:嵌套对象需配合
toRef或保持嵌套结构,否则深层属性仍会丢失响应性。 - toRaw 不可滥用:频繁绕过代理会破坏响应式一致性,仅应在性能关键路径或与第三方库交互时使用。
- readonly 是浅层冻结:嵌套对象仍可被修改,如需深层次冻结请使用
deepReadonly或递归包装。 - 性能优化:在大型列表中,使用
shallowReactive搭配toRaw可显著减少 Proxy 开销。
评论列表 0