每个 tab 对应独立 reactive 对象实现草稿隔离:1. 用 Map 缓存 tabId→draft 映射,动态创建 reactive 草稿;2. 避免引用复用,用结构赋值+reactive 初始化;3. 结合 :key 强制重渲染确保视图隔离;4. 可选 localStorage 持久化。

在 Vue 3 中用 reactive 实现多标签页各自独立的草稿箱,核心是:**每个 tab 对应一个独立的 reactive 对象,且不共享引用**。关键在于避免对象浅拷贝或引用复用,同时配合 key 或 id 做状态隔离。
1. 每个 Tab 持有独立的 reactive 草稿对象
不要把所有草稿存在一个顶层 reactive 里再靠字段区分,而应为每个 tab 动态创建专属 reactive 数据:
- 用 Map 或普通对象缓存 tabId → draft(reactive 对象) 的映射
- 新建 tab 时调用
reactive({ title: '', content: '', ... })创建新草稿 - 切换 tab 时,只读取/绑定当前 tabId 对应的那个 reactive 对象
示例:
const tabDrafts = ref(new Map()) // 或用 reactive({}),但 Map 更易管理动态 key
function openTab(tabId) {
if (!tabDrafts.value.has(tabId)) {
tabDrafts.value.set(tabId, reactive({
title: '',
content: '',
isModified: false
}))
}
}
// 在组件中使用(比如 TabContent.vue)
const currentDraft = computed(() => tabDrafts.value.get(props.tabId))
2. 避免 reactive 对象被意外复用或污染
常见错误:用 reactive({}) 初始化后直接赋值旧对象(导致引用共享);或用 ref 包裹对象却未解包使用。
将 React 应用升级到最新版本,从类组件迁移到 Hooks,并采用并发特性。用于现代化改造 React 代码库、迁移到 React Hooks 或升级到最新
立即学习“前端免费学习笔记(深入)”;
- ❌ 错误:
draft = reactive(oldDraft)—— 如果 oldDraft 是另一个 tab 的 reactive,会共享响应性甚至数据 - ✅ 正确:用结构赋值 + reactive 创建新对象:
reactive({ ...toRaw(oldDraft), id: newId })(注意 toRaw 解包原始值) - ✅ 更稳妥:从接口或模板初始化,而非复制其他 tab 的 reactive 实例
3. 结合 v-model 和 key 实现视图强隔离
即使数据隔离了,Vue 的 diff 算法仍可能复用 DOM 元素,导致输入框残留旧值。需配合 key 强制重渲染:
- 给每个 TabPane 加上唯一 key:
<tabpane :key="activeTabId"></tabpane> - 表单控件用
v-model绑定到currentDraft.title等,确保响应式更新 - 关闭 tab 时,从 Map 中 delete 对应 draft,触发自动 GC(如果没其他引用)
4. 进阶:支持草稿持久化与恢复
若需刷新不丢数据,可将 draft 内容序列化后存 localStorage(按 tabId 分区):
- 监听
draft.content变化(watch),存入localStorage.setItem(`draft_${tabId}`, JSON.stringify(draft)) - openTab 时先尝试从 localStorage 读取并
reactive(JSON.parse(...)) - 注意过滤不可序列化的值(如函数、Symbol),或用
toPlainObject工具处理

















