Handsontable — 浏览器里的 Excel
是什么
Handsontable 是一套让网页表格用起来像 Excel 的 JavaScript 数据表格库,由波兰公司 Handsoncode 在 2012 年开源。
日常类比:如果说 ag-grid 是「让浏览器能装百万行数据的展示柜」,glide-data-grid 是「用画笔直接画出来的高速画布」,那 Handsontable 就是「把 Excel 的整套手感原样搬进浏览器」——你能用 Tab 键跳格子,能拖拽填充柄复制公式,能合并单元格,能输入 =SUM(A1:A10) 让它算给你看。
GitHub 约 20k star,TypeScript 写成,AGPL v3 + 商业双许可(这一点很重要,下文展开)。
为什么重要
把它和上一篇 glide-data-grid 对照看,会发现三套同类库其实在做三件不同的事:
- AG Grid:DOM 虚拟化 + 企业级筛选 / 透视,瞄准金融后台与 BI 仪表盘
- glide-data-grid:Canvas 绘制 + 极致性能,瞄准 Notion / Airtable 这类「展示百万行」场景
- Handsontable:DOM + 完整 Excel 体验,瞄准「让用户在网页里直接做表」的应用——预算表、库存清单、人事薪资、财务报表
关键差别:前两者目标是「展示数据」,Handsontable 目标是「让用户编辑数据」。后者的难度大一个数量级——Excel 几十年积累的快捷键、撤销栈、公式引擎、合并单元格、跨表引用、复制粘贴语义……都得复刻。
它的 HyperFormula 公式引擎后来被拆出来独立开源,成了浏览器端最完整的 Excel 兼容公式实现(支持 380 多个函数)。
核心要点
Handsontable 的设计可以拆成 四件事:
1. 虚拟渲染(DOM 路线)
和 AG Grid 思路类似:屏幕上只渲染可见的几十行,滚动时复用 DOM 节点改内容。极限大约 10 万行。
为什么不像 glide 走 Canvas?因为它的核心卖点是「编辑体验」——光标、IME 输入法、复制粘贴、文本选中、辅助技术,这些跟 DOM 深度绑定。放弃 DOM 等于放弃 Excel 体感。
2. HyperFormula 公式引擎
输入 =SUM(A1:A10) 它真的会算,并且把依赖关系记在图里:A1 改了,下游所有依赖单元格自动重算。
类比:Excel 的公式引擎是一棵「谁依赖谁」的有向无环图(DAG)。改一个值,引擎按拓扑序通知下游重算,不重算无关单元格。HyperFormula 把这套机制原样搬进浏览器。
3. 完整的 Excel 操作语义
- 撤销栈:每次编辑都进栈,Ctrl+Z / Ctrl+Y 像 Excel 一样回退
- 拖拽填充柄:选中一格,拖右下角小方块,复制或推导序列(1, 2 → 3, 4, 5)
- 合并单元格:
mergeCells: [{row: 1, col: 1, rowspan: 2, colspan: 3}] - 冻结行列:
fixedRowsTop: 1/fixedColumnsLeft: 1 - 复制粘贴:Ctrl+C 出来的是 TSV,能直接粘到真 Excel 里
这些功能单看每一个都不难,难在所有功能要在一起协同——选中区域跨过冻结行还能正常拖拽,合并单元格里复制要保留合并状态,撤销要能回退合并操作本身。
4. AGPL + 商业双许可
这是最特殊的一点。Handsontable 7.0 之后从 MIT 改为 AGPL v3:
- AGPL v3:你免费用,但你的应用代码也必须开源(包括 SaaS 产品的服务器端代码)
- 商业许可:付费购买,闭源使用
这种「用版权法逼竞争对手付费,但对真开源项目仍然免费」的模式,叫「开放核心 + Copyleft 武器化」。MongoDB 的 SSPL、ElasticSearch 的 ELv2 是同类思路。
实战影响:写自家闭源 SaaS,要么买商业 license,要么换库(AG Grid 社区版 MIT、glide-data-grid MIT 都是更友好的选择)。
实践案例
案例 1:最小可跑的表格
import Handsontable from 'handsontable'import 'handsontable/dist/handsontable.full.min.css'
const container = document.getElementById('grid')const hot = new Handsontable(container, { data: [ ['苹果', 10, 5.5], ['香蕉', 20, 3.2], ], colHeaders: ['品名', '数量', '单价'], rowHeaders: true, licenseKey: 'non-commercial-and-evaluation',})注意 licenseKey——这是 AGPL 模式的实现,不写就报警告。非商业 / 评估场景填这个魔法字符串。
案例 2:开公式引擎
import HyperFormula from 'hyperformula'
const hot = new Handsontable(container, { data: [ [1, 2, '=A1+B1'], [3, 4, '=A2+B2'], ['', '', '=SUM(C1:C2)'], ], formulas: { engine: HyperFormula }, licenseKey: 'non-commercial-and-evaluation',})跑起来 C1 显示 3,C2 显示 7,C3 显示 10。改 A1 → C1 / C3 自动跟着变。
案例 3:合并单元格 + 冻结行
const hot = new Handsontable(container, { data, fixedRowsTop: 1, fixedColumnsLeft: 1, mergeCells: [ { row: 0, col: 1, rowspan: 1, colspan: 3 }, ], manualColumnResize: true, manualRowResize: true, contextMenu: true, licenseKey: 'non-commercial-and-evaluation',})右键弹出菜单(插入行 / 删除列 / 合并单元格 / 复制 / 粘贴),鼠标拖列宽行高——一行 contextMenu: true 就开了。
踩过的坑
- AGPL 是真陷阱:本地玩具项目没事,一旦上生产 SaaS,法务会拦——要么付钱,要么换库。立项前看清 license
- 大数据集要关
autoColumnSize:默认会量每个 cell 的实际宽度,10 万行下首屏要算几秒。改成固定colWidths: [100, 80, 120] afterChangehook 在初始化也会触发:用if (source === 'loadData') return判断,否则每次刷新页面都会跑业务逻辑- 复制粘贴丢精度:从 Excel 复
1.7976931348623157e+308(科学计数法)粘进来变字符串。需要在beforePaste里手动转Number() - 公式引擎不是无限大:HyperFormula 默认 sheet 上限 4 万行,超了得自己分 sheet;公式数量过多(10 万+)依赖图遍历会慢
适用 vs 不适用场景
适用:
- 用户要直接编辑数据的网页表格——预算表、库存清单、ERP 录入页
- 需要 Excel 公式 / 合并单元格 / 撤销栈 / 复制粘贴这些「Excel 体感」
- 数据量在 1 万 ~ 10 万行之间
- 商业许可预算可控(或项目本身就是开源)
不适用:
- 闭源 SaaS 又不想买 license → 选 AG Grid 社区版(MIT)或 glide-data-grid(MIT)
- 数据量 > 10 万行 + 不需要编辑 → glide-data-grid 的 Canvas 路线
- 重 Pivot / 服务端行模型 → AG Grid 企业版
- 移动端为主 → Handsontable 在小屏体验一般,Excel 风格交互本就为桌面设计
历史小故事(可跳过)
- 2012 年:波兰开发者 Marcin Warpechowski 在 GitHub 开源 Handsontable,初版只有几百行,因为 jQuery 时代缺一个像 Excel 的表格组件,迅速火起来
- 2014 年前后:成立 Handsoncode 公司商业化运营,社区版仍 MIT
- 2019 年(7.0 版本):从 MIT 改为非商业许可后又调整到 AGPL v3。社区一度炸锅,竞争对手 AG Grid 借机吸纳了一批用户
- 2020 年:把内部公式引擎拆成独立项目 HyperFormula,同样 GPLv3 + 商业双许可,反而成为开源 spreadsheet 公式引擎里最完整的一个
- 如今:商业版稳定盈利,是 JS 生态里少数靠 license 卖钱活下来的开源项目之一
学到什么
- 「展示」和「编辑」是两个数量级的难度——展示库随便写,编辑库要复刻几十年积累的人机交互细节
- license 是产品策略——MIT / Apache 2 / AGPL / SSPL 不是法律细节,是商业模式选择,立项就要想清楚
- 公式引擎的本质是依赖图——HyperFormula 把 Excel 的 DAG + 拓扑重算搬进浏览器,跟 spreadsheet / 反应式编程是同一族
- DOM 路线还远没死——只要核心卖点是「编辑体验」,DOM 仍然是最务实的选择,Canvas 路线的代价太大
- 开源不等于免费——AGPL 是给商业使用者的账单,不是慈善
延伸阅读
- 仓库:handsontable/handsontable
- 公式引擎:handsontable/hyperformula
- 文档:handsontable.com/docs
- AGPL 解读:Why we relicensed
- ag-grid —— DOM 虚拟化 + 企业级 BI,对照阅读
- glide-data-grid —— Canvas 路线,性能极限对比
关联
- ag-grid —— 同为 DOM 路线,但目标是「展示」而非「编辑」
- glide-data-grid —— Canvas 路线,性能 vs 编辑体验的另一极
- react —— Handsontable 提供 React 包装器,但内核是框架无关的 vanilla JS
- d3 —— 数据可视化老牌,与 Handsontable 解的是不同问题(图形 vs 表格)
反向链接
- ag-grid —— AG Grid — 企业级数据表格
- canvas-datagrid —— canvas-datagrid — 整张表只用一块 canvas 画
- d3 —— D3.js — 不是图表库,是写图表库的乐高
- glide-data-grid —— glide-data-grid — Canvas 画出来的百万行表格
- react —— React UI 组件库
- tabulator —— Tabulator — 纯 JS 交互式表格