作品 · Works

XExcel

20231TypeScriptKonvaSpreadsheetFormula Engine
XExcel

一个把 ProseMirror 架构移植到电子表格领域的浏览器端 Excel:一切皆 State,所有修改只能经 Transaction/Step(Step 可序列化),视图只是状态的投影。pnpm monorepo 三包单向分层(excel-react → excel-view → excel-core,core 零 DOM 依赖可独立作 SDK 分发),约 1.7 万行 strict TypeScript,533 个单元测试 + 38 个真实浏览器 e2e 场景。

项目特点

  • State + Transaction + Plugin 架构:excel-view 与 React 层永不直接改文档;插件系统带 PluginKey 与 someProp 责任链分发,撤销/重做、剪贴板、拖拽移动、填充柄、多区域选择等内建交互全部以平级插件实现——「能力即插件」在表格领域跑通。
  • Canvas 视口虚拟化:命令式 Konva 三层画布(grid / cell / overlay,全部 listening: false 零事件开销),只绘制滚动偏移反解出的可见行列区间;冻结窗格拆四象限独立 clip 渲染,所有重绘经 rAF 合帧。
  • 全自研公式引擎:lexer → parser → eval 三段式手写,29 个 Excel 语义函数(IF / SUMIF / COUNTIF / 日期族 / 文本族……),复刻 Excel 隐式类型转换、比较序(数字 < 字符串 < 布尔)与 #DIV/0! 错误值体系,支持跨表引用。
  • xlsx 深度互操作:经 exceljs 实现值 / 公式 / 样式 / 合并 / 冻结 / 筛选 / 条件格式 / 数据验证 8 类特性的双向导入导出全映射,另有 CSV 互操作与 localStorage 防抖自动保存(损坏自愈)。
  • 测试是真环境:533 个单测之外,38 个 e2e 场景驱动本机真实 Chrome 跑回归,不是 jsdom 假环境。

技术难点

架构选型即难点。 表格的编辑语义(单元格寻址、区域操作、公式引用级联)与富文本完全不同,ProseMirror 模型不能照搬:Step 要可序列化以支撑撤销栈与未来协同,结构级联(registerStructureCascade)要在行列插删时联动修正公式引用、合并区与筛选区。

Canvas 渲染的事件与性能两难。 DOM 方案在万级单元格下节点爆炸,Canvas 方案又丢失全部交互语义。解法是三层画布全关事件监听、由 EditorView 统一命中分派,绘制侧视口虚拟化 + rAF 合帧,让滚动时只重绘可见区。

Excel 兼容是个无底洞。 公式引擎的难不在解析而在语义:隐式类型转换、奇怪的比较序、错误值传播,每一项都要对着 Excel 行为复刻,否则用户粘贴过来的真实表格就算错。