- 前端
- UI组件
【免费下载链接】handsontable
JavaScript Data Grid / Data Table with a Spreadsheet Look & Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡
Handsontable 10.0.0 于 2021 年 9 月 29 日发布,本次版本升级带来了一系列破坏性变更,涉及渲染钩子(hooks)的命名与语义、HyperFormula 公式引擎的依赖版本、多个配置选项的默认值以及默认字体样式。本文以官方迁移文档为主体,结合当前仓库源码(hooks 常量定义、CopyPaste 插件实现、metaSchema 选项默认值 等)逐项拆解,帮助你对照检查自己的应用代码,完成从 9.0 到 10.0 的平滑迁移。
本文适用的应用场景:任何基于 Handsontable 9.x 构建、需要升级到 10.x 的 JavaScript / React / Angular / Vue 项目。读完本文,你将掌握渲染钩子的新旧命名对应关系、controller参数的替换规则、HyperFormula 依赖的升级路径,以及受影响的默认值清单,并能据此快速定位需要修改的代码位置。
迁移前的准备:了解 10.0.0 破坏性变更总览
Handsontable 10.0.0 的全部变更细节记录在 CHANGELOG.md 中,本次迁移共涉及 6 项破坏性变更:
- 重命名
beforeRender/afterRender钩子为beforeViewRender/afterViewRender,并赋予旧名称全新的语义; - 可选依赖 HyperFormula 从
0.6.2升级到^1.1.0; - 配置选项
autoWrapCol/autoWrapRow的默认值从true改为false; - CopyPaste 插件的
rowsLimit/columnsLimit默认值从1000改为Infinity; - 统一
beforeOnCellMouseDown/beforeOnCellMouseOver钩子的第四个参数controller的命名与结构; - 为
.handsontable类下的所有元素新增默认字体族、字号、字重和颜色。
下面按照官方迁移指南的五步流程,逐一说明每项变更的具体内容、影响范围与应对方法。
Step 1:重命名你的 Handsontable 渲染钩子
10.0.0 对渲染流程做了重新梳理,最直观的体现就是钩子名称的变更。如果你在应用中使用过beforeRender或afterRender钩子,请按下表更新名称:
| 升级前(9.x) | 升级后(10.x) |
|---|---|
beforeRender | beforeViewRender |
afterRender | afterViewRender |
新名称的触发时机
从源码看,新钩子的触发时机与旧钩子基本对应:beforeViewRender在 Handsontable 的视图渲染引擎开始渲染之前触发,afterViewRender在视图渲染引擎渲染完成之后、但尚未重绘选区边框和同步滚动之前触发。它们都会收到一个isForced布尔参数:
isForced = true:渲染由设置变更、数据变更或需要完整渲染周期的逻辑触发;isForced = false:渲染由滚动或移动选区等轻量操作触发。
这些语义在 hooks 常量定义 中有完整注释说明。
旧名称现在做了什么「新事情」
注意,升级后仍然存在名为beforeRender和afterRender的钩子,但它们的含义完全不同了。新版语义如下(见 hooks 常量定义):
beforeRender:在 Handsontable 业务逻辑执行完毕、渲染引擎开始调用 Core 逻辑、renderers、单元格 meta 等来更新视图之前触发。isForced = false时仍会重绘新进入视口的行列,但滚动本身不会触发该钩子;afterRender:在视图渲染引擎更新视图之后触发,参数规则与beforeRender相同。
因此升级后请务必检查你的钩子注册代码:
- 原来监听“每次视图绘制前后”的
beforeRender/afterRender→ 改为beforeViewRender/afterViewRender; - 确认你确实需要新版
beforeRender/afterRender的语义后再注册它们,不要无意识地同时挂载新旧两套钩子导致逻辑重复。
对应的钩子测试(beforeViewRender.spec.js)验证了beforeViewRender仅在慢渲染路径(draw()被调用)上触发,且beforeViewRender一定先于afterViewRender执行。渲染引擎层面,Walkontable 的绘制循环也遵循“核心的beforeViewRender在首轮绘制前触发一次、afterViewRender在末轮绘制后触发一次”的顺序(见 drawCycle.ts 的注释)。
Step 2:适配 HyperFormula 依赖升级
Handsontable 10.0.0 将可选的 HyperFormula 依赖从0.6.2升级到^1.1.0,这会影响Formulas插件(公式计算)的使用者。
你的依赖是否需要同步升级
HyperFormula 是Formulas插件的可选依赖,只有使用公式功能的项目才需要处理。当前仓库中 handsontable/package.json 声明的 hyperformula 版本为^3.0.0(后续版本又做了多次升级),而 10.0.0 时代的对应版本是^1.1.0。作为从 9.0 迁移上来的项目,你需要:
- 将 package.json 中声明的
hyperformula版本升级到与你的 Handsontable 10.x 版本匹配的范围(10.0.x 对应^1.1.0); - 阅读 HyperFormula 官方 0.6.x → 1.0.x 迁移指南,处理引擎 API 层面的破坏性变更。
引擎注册机制仍兼容
从源码结构看,Formulas插件的引擎注册逻辑(register.ts)支持三种配置方式:直接传入引擎类、传入引擎实例、或传入{ hyperformula: engineClass }形式。引擎实例通过engineClass.buildEmpty(engineSettings)创建,并注册自定义函数、语言包与命名表达式(register.ts)。也就是说,升级 HyperFormula 后,你仍然可以用相同的方式把新版本引擎接入Formulas插件,主要成本集中在引擎自身 API 的适配上。
Step 3:适配配置选项的新默认值
10.0.0 调整了四类配置项的默认值,如果之前依赖旧默认值,行为会发生变化,需要显式配置以恢复原有体验。
autoWrapCol / autoWrapRow:从 true 改为 false
autoWrapCol和autoWrapRow控制键盘导航在到达表格边缘时的「换行」行为,默认值从true改为false(详见 CHANGELOG.md)。
JavaScript 写法对比:
| 升级前(9.x) | 升级后(10.x) |
|---|---|
autoWrapCol: true | autoWrapCol: false |
autoWrapRow: true | autoWrapRow: false |
React 写法对比:
| 升级前(9.x) | 升级后(10.x) |
|---|---|
autoWrapCol={true} | autoWrapCol={false} |
autoWrapRow={true} | autoWrapRow={false} |
升级后,当你选中表格最底部的单元格时按方向键 ⬇ 不会再有反应(autoWrapCol: false时不会跳到下一列顶部);同样,选中行首单元格按 ⬅ 或Shift+Tab也不会跳转到上一行末尾(autoWrapRow: false时不会换行)。如果你希望保留 9.x 的环绕导航体验,请显式设置:
// 恢复 9.x 的键盘环绕导航行为 const hot = new Handsontable(container, { autoWrapCol: true, autoWrapRow: true, // ... 其他配置 });这两个选项的当前默认值false已在 metaSchema.ts 的@default注释与默认值声明中得到确认,对应的行为说明(如autoWrapCol: false时按 ⬇ 不做任何事、autoWrapCol: true时按 ⬇ 跳到下一列最上方单元格)也直接写在源码文档注释中。autoWrapRow还受tabNavigation、minSpareCols等其他选项的优先级影响(见 hooks 常量定义 中beforeRowWrap钩子的说明)。针对此默认值的回归测试位于 autoWrapCol.spec.js。
CopyPaste 的 rowsLimit / columnsLimit:从 1000 改为 Infinity
CopyPaste插件的rowsLimit和columnsLimit用于限制复制到剪贴板的最大行数 / 列数,默认值从1000改为Infinity,意味着复制操作不再受默认数量上限约束。
JavaScript 写法对比:
| 升级前(9.x) | 升级后(10.x) |
|---|---|
rowsLimit: 1000 | rowsLimit: Infinity |
columnsLimit: 1000 | columnsLimit: Infinity |
React 写法对比:
| 升级前(9.x) | 升级后(10.x) |
|---|---|
rowsLimit={1000} | rowsLimit={Infinity} |
columnsLimit={1000} | columnsLimit={Infinity} |
从 CopyPaste 插件源码 看,DEFAULT_SETTINGS中rowsLimit与columnsLimit均声明为Infinity,类属性默认值同样是Infinity;插件在初始化时通过isNaN判断用户是否显式传值,未传则保持默认(copyPaste.ts)。最终复制范围会调用剪贴板尺寸计算逻辑,将选区范围与rowsLimit、columnsLimit一起参与裁剪(copyPaste.ts)。
迁移建议:如果你曾经依赖1000行 / 列的隐性上限来防止大数据量复制卡顿,升级后请显式设置合理的rowsLimit/columnsLimit值;如果项目一直希望复制不受限制,则无需任何改动。
Step 4:适配钩子参数的统一命名
10.0 统一了beforeOnCellMouseDown和beforeOnCellMouseOver钩子第四个参数的命名与结构:
| Handsontable 钩子 | 升级前参数名 | 升级后参数名 |
|---|---|---|
beforeOnCellMouseDown | blockCalculations | controller |
beforeOnCellMouseOver | blockCalculations | controller |
controller 对象的结构变化
两个钩子中的controller对象不仅改了名字,内部结构也做了调整——cells属性更名为cell:
blockCalculations(升级前) | controller(升级后) |
|---|---|
rowcolumncells | rowcolumncell |
新结构下,controller.row、controller.column、controller.cell各自包含一个布尔值,用于允许或禁止对应区域的选区变更(参见 hooks 常量定义 中两个钩子的 JSDoc 注释)。
例如,9.x 时代常见的「阻止特定单元格被选中」写法:
// 9.x 写法(已废弃) beforeOnCellMouseDown: (event, coords, TD, blockCalculations) => { blockCalculations.cells = true; }迁移后应改为:
// 10.x 写法 beforeOnCellMouseDown: (event, coords, TD, controller) => { controller.cell = true; }受影响的插件
参数重命名影响以下插件(它们内部会通过该参数控制选区交互):
ColumnSorting(columnSorting.ts)MultiColumnSortingManualColumnMoveManualRowMoveNestedHeaders
如果你在应用中直接调用这些插件并传入了blockCalculations参数,务必同步更新为controller及controller.cell。该变更同时收录在 CHANGELOG.md 的破坏性变更列表中。
Step 5:适配默认字体样式变更
为了让 Handsontable 开箱即用就有良好的外观,10.0 为.handsontableCSS 类下的所有元素新增了默认的font-family、font-size、font-weight和color属性。
源码中的实现证据
在 base.scss 中,.handsontable类声明了:
font-family:通过mixins.font-family引入,实际取值为var(--ht-font-family), -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif(见 _mixins.scss),优先使用主题变量,回退到系统字体栈;font-size:var(--ht-font-size);font-weight:var(--ht-font-weight);color:var(--ht-foreground-color)。
也就是说,当前仓库中字体样式已经变量化,便于通过主题定制覆盖。而在 10.0.0 刚引入默认字体时,这项变更是破坏性的——如果你的应用没有显式覆盖这些属性,升级后网格的字体外观会直接改变。
迁移建议
- 升级后检查应用的整体视觉效果,确认网格字体是否符合预期;
- 若希望自定义字体,可在自己的 CSS 中覆盖
.handsontable内的字体属性(当前仓库推荐通过主题 CSS 变量覆盖); - 若你的应用全局重置了字体样式(如
* { font-family: ... }),需注意其与 Handsontable 默认样式的优先级关系。
升级清单:从 9.0 迁移到 10.0 的完整检查表
将上述五步整理为一份可勾选的检查清单,方便你在实际项目中逐项核对:
- 搜索代码中的
beforeRender/afterRender钩子,确认是否表示“视图渲染前后”,若是则重命名为beforeViewRender/afterViewRender; - 确认新版
beforeRender/afterRender钩子的新语义是否是你需要的,避免新旧钩子逻辑混淆; - 若使用
Formulas插件,将hyperformula依赖升级到与 Handsontable 10.x 匹配的版本(10.0.x 对应^1.1.0),并适配 HyperFormula 引擎 API; - 检查键盘导航体验,若依赖 9.x 的环绕导航,显式设置
autoWrapCol: true和autoWrapRow: true; - 若依赖复制数量上限,显式设置
rowsLimit/columnsLimit(默认已变为Infinity); - 将
beforeOnCellMouseDown/beforeOnCellMouseOver中的blockCalculations参数重命名为controller,并把blockCalculations.cells改为controller.cell; - 检查受影响的插件(
ColumnSorting、MultiColumnSorting、ManualColumnMove、ManualRowMove、NestedHeaders)中对该参数的使用; - 升级后检查网格字体外观,必要时显式覆盖字体样式;
- 运行应用的完整测试套件(包括键盘导航、复制粘贴、排序、移动、嵌套表头等场景),确认无回归。
参考资源
- 10.0.0 完整变更日志:CHANGELOG.md
- 官方 Changelog 文档:docs/content/guides/upgrade-and-migration/changelog/changelog.md
- 钩子常量与 JSDoc 语义定义:handsontable/src/core/hooks/constants.ts
- 渲染钩子测试用例:handsontable/src/tests/hooks/beforeViewRender.spec.js
- CopyPaste 插件默认值与裁剪逻辑:handsontable/src/plugins/copyPaste/copyPaste.ts
- 配置选项默认值(
autoWrapCol/autoWrapRow):handsontable/src/dataMap/metaManager/metaSchema.ts - 默认字体样式实现:handsontable/src/styles/base/_base.scss、handsontable/src/styles/utils/_mixins.scss
按上述五个步骤完成改动后,你的应用就运行在了 Handsontable 10.0 上,可以继续享受后续版本带来的性能与一致性改进。
- 前端
- UI组件
【免费下载链接】handsontable
JavaScript Data Grid / Data Table with a Spreadsheet Look & Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡
相关推荐
3步掌握Genanki:Python自动化创建Anki卡片的终极指南
3步掌握Genanki:Python自动化创建Anki卡片的终极指南 还在为手动制作Anki卡片而烦恼吗?Genanki这个强大的Python库将彻底改变你的学
教育leebaird/discover敏感信息检测:如何快速发现和防护数据泄露风险
leebaird/discover敏感信息检测:如何快速发现和防护数据泄露风险 在数字化时代,数据泄露已成为企业和个人面临的重大安全威胁。leebaird/di
网络安全TRL v0 到 v1 迁移指南:默认值变更、参数重命名与 None 值处理
TRL v0 到 v1 迁移指南:默认值变更、参数重命名与 None 值处理 本指南面向所有从 TRL v0 升级到 v1 的开发者,系统梳理 v1 引入的破坏
人工智能大模型强化学习RLHF预训练微调LoRA
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考