Files
new-markdown/docs/18-tab-keepalive.md
Muse 4a527da655 feat(editor): 标签编辑器保活,切换立即呈现(docs/18)
最近用过的 6 个标签保持挂载、隐藏而非销毁,切回零解析零序列化、各窗格
保留滚动位置;超限窗格卸载走最终回写。引用改为按标签注册表 + 活动变化
effect 统一指向;外部重载 epoch 按标签粒度、抑制闸门对所有标签生效。
EditorPane 新增就绪状态:首次打开大文件显示「正在打开文档…」加载态。
打印守卫:只出活动窗格。vitest 87 通过 + 2 跳过(新增 pane-loading 1 例)。
2026-11-14 13:06:39 +08:00

2.4 KiB
Raw Permalink Blame History

标签切换保活与加载状态(2026-11-14)

用户反馈

切换大文件时要等很久才能切回去,希望立即切回;至少要有加载进度/状态。

根因

原架构下每次切标签都销毁旧编辑器(全量序列化回写)并为新标签从 Markdown 全量解析重建编辑器。阶段 6 实测(jsdom 悲观口径):626K 字符建模 29.8s、 序列化 2.6s——大文档来回切换就是把这个成本反复付两遍。

改造:编辑器保活

  • App 改为按标签渲染多个编辑器窗格,只有活动窗格可见,其余 display:none 保持挂载:切回时零解析、零序列化,立即显示;每个窗格自带滚动容器, 连滚动位置都各自保留。
  • 保活上限:最近用过的 6 个标签(LRU)。超出的窗格卸载,卸载前走既有的 最终回写(syncEditorContent),内容不丢,之后再切到时按状态内容重建。
  • 编辑器引用改为注册表(paneApisRef: tabId → api);onReady 只登记, 共享引用(查找/大纲跳转/源码锚点)由「活动标签变化」effect 统一指向 活动窗格,后台窗格就绪/卸载不会再冲掉活动窗格的引用。
  • 外部重载(reloadTabFromDisk)的 epoch 重挂改为按标签粒度(paneEpochs), 且闸门(抑制卸载回写)对所有标签生效——保活后非活动标签也可能正挂载, 旧实现只处理活动标签会漏。退出源码模式的重建同理改为按标签 bump。
  • 状态栏光标只接受活动窗格的回调,后台窗格不再干扰。

加载状态

  • EditorPane 新增就绪状态:编辑器 create() 完成前在窗格内显示 「正在打开文档…」+ 旋转指示(.pane-loading),就绪即撤下。 首次打开大文件时标签立刻出现、窗格明确处于加载中,不再是无反馈的卡住。 解析是单线程同步计算,做不了真实百分比进度,用明确的加载态代替。

打印

@media print 增加守卫:.tab-pane 打印时隐藏、仅 .active 出纸, 避免保活窗格被通用 display:block 规则一起打出来。

验证

  • tsc 0 错误;vitest 87 通过 + 2 跳过(新增 tests/pane-loading.test.tsx: 创建未完成时显示加载提示、完成后撤下并回传就绪 API);构建通过。
  • 待真机验:两个大文档来回切换应立即呈现;首次打开大文档有加载态; 外部修改重载、源码模式进出、打印只出当前文档。