最近用过的 6 个标签保持挂载、隐藏而非销毁,切回零解析零序列化、各窗格 保留滚动位置;超限窗格卸载走最终回写。引用改为按标签注册表 + 活动变化 effect 统一指向;外部重载 epoch 按标签粒度、抑制闸门对所有标签生效。 EditorPane 新增就绪状态:首次打开大文件显示「正在打开文档…」加载态。 打印守卫:只出活动窗格。vitest 87 通过 + 2 跳过(新增 pane-loading 1 例)。
46 lines
2.4 KiB
Markdown
46 lines
2.4 KiB
Markdown
# 标签切换保活与加载状态(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);构建通过。
|
||
- 待真机验:两个大文档来回切换应立即呈现;首次打开大文档有加载态;
|
||
外部修改重载、源码模式进出、打印只出当前文档。
|