Handsontable 列隐藏(HiddenColumns)完整指南:配置、上下文菜单与 API 实战
【免费下载链接】handsontableJavaScript Data Grid / Data Table with a Spreadsheet Look & Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡项目地址: https://gitcode.com/gh_mirrors/ha/handsontable
本文是一份基于 Handsontable 开源仓库的列隐藏(Column Hiding)实战指南。通过HiddenColumns插件,你可以隐藏网格中的任意列,隐藏后的列不再渲染为 DOM 元素,从而减少界面杂乱并显著提升大数据量下的渲染性能——同时源数据保持原样。读完本文,你将掌握:如何启用列隐藏、如何通过 4 个步骤完成默认隐藏列、UI 指示器、上下文菜单与复制粘贴行为的完整配置,以及如何用插件 API 在运行时动态隐藏/显示列。
Overview:什么是列隐藏
"Hiding a column"(隐藏一列)意味着该列不会作为 DOM 元素被渲染。这与"列被清空"或"数据被删除"完全不同:
- 源数据不会被修改:
HiddenColumns插件不触碰你传入的原始数据数组。 - 插件不参与数据转换:由
getData*()系列方法返回的数据形状保持完整——隐藏列的数据依然存在于返回值中,只是界面上不可见。
这两点可以从插件源码的类注释中得到印证(见 hiddenColumns.ts)。这也意味着列隐藏是一种纯展示层的操作,非常适合"按角色/场景裁剪可见字段"这类需求:例如只让某些用户看到 SKU、品名、价格列,而隐藏库存、供应商等敏感或不必要的列。
启用列隐藏
要启用列隐藏,在 Handsontable 的初始化配置中加入hiddenColumns选项即可。传入一个对象(或true)即视为启用插件。
以仓库中的官方示例 example1.js 为例,一个最小的启用配置如下:
import Handsontable from 'handsontable/base'; import { registerAllModules } from 'handsontable/registry'; // 注册 Handsontable 的全部模块 registerAllModules(); const container = document.querySelector('#example1'); new Handsontable(container, { licenseKey: 'non-commercial-and-evaluation', data: [ ['SKU-4821', 'Stainless Steel Water Bottle', 'Harbor Goods', 'Drinkware', 'Seattle', 142, 24.99, 40, 'In stock', '2026-03-12'], // ... 更多数据行 ], height: 200, colHeaders: true, rowHeaders: true, contextMenu: true, // 启用 `HiddenColumns` 插件 hiddenColumns: { columns: [2, 4, 6], indicators: true, }, autoWrapRow: true, autoWrapCol: true, });在 React、Vue 3 与 Angular 等框架封装中,配置方式同样是通过组件属性或 settings 对象传入,完整的可运行示例分别见:
- React:example1.jsx(通过
<HotTable hiddenColumns={{ columns: [2, 4, 6], indicators: true }} />传入) - Vue 3:example1.vue(通过
ref<GridSettings>的hiddenColumns字段传入) - Angular:example1.ts(通过
GridSettings的hiddenColumns字段传入)
设置列隐藏:4 个步骤
Step 1:指定默认隐藏的列
要"既启用列隐藏,又指定默认隐藏哪些列",把hiddenColumns配置选项设置为一个对象,并在对象内添加columns配置项,赋值为列索引数组:
hiddenColumns: { // 指定默认隐藏的列 columns: [3, 5, 9], },完整示例见 example2.js。这样配置后,索引为 3、5、9 的三列在网格初始化时即被隐藏。
需要说明的是,这里的列索引是视觉索引(visual column index)。从源码 hiddenColumns.ts 可以看到,isValidConfig()会校验索引是否为非负整数且小于当前列数(visualColumn < nrOfColumns),超出边界的索引会被视为非法配置而忽略。
Step 2:显示 UI 指示器
为了直观地看出哪些列当前被隐藏,可以显示 UI 指示器。在hiddenColumns对象中把indicators属性设为true:
hiddenColumns: { columns: [3, 5, 9], // 显示标记隐藏列的 UI 指示器 indicators: true, },完整示例见 example3.js。开启后,隐藏列两侧相邻的表头会出现箭头状的视觉标记,鼠标悬停即可展开/收起隐藏列。
注意事项:如果同时使用
NestedHeaders插件和HiddenColumns插件,还必须把colHeaders属性设为true,否则indicators不会生效。
从源码看,指示器的渲染依赖两个内部钩子(见 hiddenColumns.ts):#onAfterGetColHeader会给隐藏列左右相邻的表头TH元素添加afterHiddenColumn/beforeHiddenColumn两个 CSS 类;同时#onModifyColWidth(hiddenColumns.ts)会对隐藏列返回宽度0,并给紧邻隐藏列的可视列额外增加 15px 宽度(前提是hasColHeaders()为真),为指示器腾出空间。
Step 3:设置上下文菜单项
要在界面上方便地隐藏/取消隐藏列,可以把列隐藏菜单项加到 Handsontable 的上下文菜单中。
方式一:同时启用插件,自动添加菜单项。同时启用ContextMenu插件和HiddenColumns插件后,上下文菜单会自动附加隐藏列与显示列的菜单项:
// 启用上下文菜单 contextMenu: true, // 启用 `HiddenColumns` 插件 // 会自动添加上下文菜单的列隐藏项 hiddenColumns: { columns: [3, 5, 9], indicators: true, },完整示例见 example4.js。这一行为在源码中由#onAfterContextMenuDefaultOptions钩子实现(hiddenColumns.ts):它会把一个分隔符以及hideColumnItem、showColumnItem两个预定义菜单项追加到默认菜单项列表末尾。
方式二:单独添加菜单项。也可以不依赖自动注入,而是通过contextMenu参数直接指定hidden_columns_show与hidden_columns_hide这两个字符串键:
// 单独添加列隐藏的上下文菜单项 contextMenu: ['hidden_columns_show', 'hidden_columns_hide'], hiddenColumns: { columns: [3, 5, 9], indicators: true, },完整示例见 example5.js。这两个菜单项的定义位于插件目录下:hideColumn.ts 与 showColumn.ts。从hideColumn.ts的实现可以看到菜单项的几个实用细节:
- 菜单显示名会根据当前选区跨度自动切换单复数(
CONTEXTMENU_ITEMS_HIDE_COLUMN的pluralForm)。 - 点击后会计算选中范围
start到end之间的全部列索引,调用hiddenColumnsPlugin.hideColumns(...)执行隐藏。 - 隐藏完成后,会通过
getNearestNotHiddenIndex()自动把选区移动到最近的可视列,避免选区落到不可见的列上。
Step 4:设置复制粘贴行为
默认情况下,隐藏列会参与复制和粘贴(即复制选区时隐藏列的内容会被一并复制,粘贴时也会写入隐藏列)。
如果希望把隐藏列排除在复制粘贴之外,在hiddenColumns对象中把copyPasteEnabled属性设为false:
contextMenu: ['hidden_columns_show', 'hidden_columns_hide'], hiddenColumns: { columns: [3, 5, 9], indicators: true, // 把隐藏列排除在复制粘贴之外 copyPasteEnabled: false, },完整示例见 example6.js。
这一行为在源码中有两处支撑(见 hiddenColumns.ts 与 hiddenColumns.ts):
#onAfterGetCellMeta:当copyPasteEnabled === false时,为隐藏列中的单元格设置skipColumnOnPaste: true,并打上内部标记符号;取消隐藏时再移除该标记。#onModifyCopyableRange:当copyPasteEnabled为true(默认值)时原样返回复制范围;为false时则把范围按隐藏列切分为多个不包含隐藏列的子范围。
配置选项参考
以下是HiddenColumns插件支持的配置选项,其默认值可直接从源码中的DEFAULT_SETTINGS确认(见 hiddenColumns.ts):
| 选项 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
columns | 否 | 数组 | [] | 指定默认隐藏的列索引(视觉索引) |
indicators | 否 | 布尔 | false | 是否显示隐藏列的 UI 指示器 |
copyPasteEnabled | 否 | 布尔 | true | 隐藏列是否参与复制粘贴 |
Column hiding API 方法
对于最常见的运行时列隐藏/显示任务,可以直接调用插件 API。所有方法都要求先通过getPlugin()拿到HiddenColumns插件实例:
const plugin = hot.getPlugin('hiddenColumns');在 React / Vue 3 封装中,需要先通过组件引用(React 的
ref或 Vue 的hotInstance属性)拿到 Handsontable 实例,再调用上述 API。
隐藏单列
const plugin = hot.getPlugin('hiddenColumns'); plugin.hideColumn(4); // 重新渲染你的 Handsontable 实例 hot.render();隐藏多列
两种等价写法:要么把列索引作为多个参数传给hideColumn(),要么把索引数组传给hideColumns():
const plugin = hot.getPlugin('hiddenColumns'); plugin.hideColumn(0, 4, 6); // 或 plugin.hideColumns([0, 4, 6]); // 重新渲染你的 Handsontable 实例 hot.render();显示单列
const plugin = hot.getPlugin('hiddenColumns'); plugin.showColumn(4); // 重新渲染你的 Handsontable 实例 hot.render();显示多列
const plugin = hot.getPlugin('hiddenColumns'); plugin.showColumn(0, 4, 6); // 或 plugin.showColumns([0, 4, 6]); // 重新渲染你的 Handsontable 实例 hot.render();调用这些方法后,务必调用hot.render()重新渲染,才能看到变更生效。
其他实用 API
除了上述四个方法,插件还提供两个查询方法(见 hiddenColumns.ts):
plugin.getHiddenColumns():返回当前所有隐藏列的视觉索引数组。plugin.isHidden(column):判断指定视觉索引的列当前是否被隐藏。
源码级原理:插件内部工作机制
如果想知道"隐藏列"在底层是如何实现的,可以从 hiddenColumns.ts 的源码窥见一二:
- 索引映射(Index Map):插件启用时,会在
hot.columnIndexMapper上注册一个类型为hiding的索引映射(见 hiddenColumns.ts)。这个映射记录了每个物理列是否被隐藏,是"不渲染隐藏列"的核心数据结构。 - 视觉索引与物理索引的转换:
hideColumn()/showColumn()接收的是视觉索引,内部通过toPhysicalColumn()转为物理索引写入映射(见 hiddenColumns.ts),而getHiddenColumns()则反过来用toVisualColumn()输出视觉索引。理解这一点有助于在嵌套行、列移动等场景中正确传参。 - 批量更新:
hideColumns()内部通过hot.batchExecution()批量写入映射值,保证多列隐藏在一次渲染内完成(见 hiddenColumns.ts)。 - 可拦截的钩子:隐藏/显示操作都会先触发
beforeHideColumns/beforeUnhideColumns钩子,如果钩子返回false,操作会被中止(见 hiddenColumns.ts);随后触发afterHideColumns/afterUnhideColumns钩子。这为业务侧提供了"隐藏前校验、隐藏后联动"的扩展点。 - 插件优先级:
PLUGIN_PRIORITY = 310(见 hiddenColumns.ts),决定了它与其他插件(如NestedHeaders、ContextMenu)的初始化顺序。
相关 API 参考
配置选项
hiddenColumns(本文档对应的配置入口)
钩子(Hooks)
beforeHideColumns:隐藏列之前触发,返回false可取消隐藏afterHideColumns:隐藏列之后触发beforeUnhideColumns:显示列之前触发,返回false可取消显示afterUnhideColumns:显示列之后触发
插件
HiddenColumns:插件本体,源码位于 handsontable/src/plugins/hiddenColumns/hiddenColumns.ts,上下文菜单项位于 contextMenuItem 目录下。
小结
完成本指南后,你已经可以:在不修改源数据的前提下隐藏网格中的任意列;通过hiddenColumns.columns配置默认隐藏列;用indicators让隐藏状态一目了然;通过上下文菜单让用户自行隐藏/显示列;用copyPasteEnabled控制隐藏列是否参与复制粘贴;并通过getPlugin('hiddenColumns')拿到插件实例,在运行时用hideColumn()/hideColumns()/showColumn()/showColumns()动态调整列的可见性。
【免费下载链接】handsontableJavaScript Data Grid / Data Table with a Spreadsheet Look & Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡项目地址: https://gitcode.com/gh_mirrors/ha/handsontable
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考