Univer 表格 UI 插件指南:使用 @univerjs/sheets-table-ui 为电子表格接入结构化表格交互
【免费下载链接】univerUniver is a full-stack framework for creating and editing spreadsheets / word processor / presentation on both web and server.项目地址: https://gitcode.com/GitHub_Trending/un/univer
@univerjs/sheets-table-ui是 Univer Sheets 的结构化表格(Structured Table)UI 层插件,它把「插入表格」「筛选面板」「表格选择器」「行/列增删菜单」「主题切换」等表格相关的界面与交互能力集成到 Univer 电子表格中。本文以 packages/sheets-table-ui/README.md 为主线,结合仓库源码讲解该插件的安装、注册、配置、命令与控制器体系,帮助你快速在项目中落地可用的表格交互工作流。
包概览与定位
在 Univer 的模块化架构中,@univerjs/sheets-table-ui与「表格(Table)」相关的几个包分工明确:
| Package | 定位 |
|---|---|
@univerjs/sheets-table | 表格核心模型层,提供TableManager、SheetTableService、SetSheetTableFilterCommand等数据与命令能力(不含 UI) |
@univerjs/sheets-table-ui | 表格 UI 层,提供菜单、筛选面板、选择器、主题面板、渲染控制器等界面交互 |
从 package.json 的依赖可以看出,UI 层依赖了@univerjs/sheets-table(表格核心模型)、@univerjs/sheets(电子表格)、@univerjs/sheets-ui(电子表格 UI 基础)以及@univerjs/engine-render(渲染引擎)等,说明它是在表格核心能力之上叠加的交互层。
包元信息
README 的 Package Overview 表格给出了关键打包信息:
| 属性 | 值 |
|---|---|
| Package | @univerjs/sheets-table-ui |
| UMD global | UniverSheetsTableUi |
| CSS | 是(需要单独引入lib/index.css) |
| Locales | 是(内置 20 种语言) |
| Facade entry | 否 |
- UMD global:使用 CDN 的 UMD 构建时,全局变量名为
UniverSheetsTableUi。 - CSS:该包包含样式文件,使用前必须导入。
- Locales:内置了
ar-SA、ca-ES、de-DE、en-US、es-ES、fa-IR、fr-FR、id-ID、it-IT、ja-JP、ko-KR、pl-PL、pt-BR、ru-RU、sk-SK、vi-VN、zh-CN、zh-HK、zh-TW等语言资源(见 src/locale 目录)。 - Facade entry:本包未提供 Facade 入口(README 中标记为 No),意味着你主要直接通过插件与命令 API 使用它,而不是通过
FWorksheet等 Facade 对象。
安装
README 提供了两种安装方式(包管理器任选其一,注意保持所有@univerjs/*包版本一致):
pnpm add @univerjs/sheets-table-ui # or npm install @univerjs/sheets-table-ui提示:本仓库采用 pnpm workspace 管理,仓库内该包版本为
1.0.0-beta.2(见 package.json)。README 强调Keep all@univerjs/*packages on the same version,这是 Univer 各插件包之间的版本耦合约定,混用不同版本可能导致类型或运行时的不兼容。
使用:注册插件
README 给出了最小注册代码:
import '@univerjs/sheets-table-ui/lib/index.css'; import EnUS from '@univerjs/sheets-table-ui/locale/en-US'; import { UniverSheetsTableUIPlugin } from '@univerjs/sheets-table-ui'; univer.registerPlugin(UniverSheetsTableUIPlugin); // Merge EnUS into your Univer locale map when this package contributes UI text.这里有三点值得展开:
- CSS 必须单独引入:
@univerjs/sheets-table-ui/lib/index.css对应 src/global.css,入口 src/index.ts 通过import './global.css'声明了样式依赖。构建产物(publishConfig 的exports映射)会把样式输出到lib/es/index.css。 - Locale 合并:该包贡献了界面文案(如
sheets-table-ui.title、sheets-table-ui.condition.empty等),需要把对应语言包合并进 Univer 的 locale 映射后再创建 Univer 实例。语言包文件位于 src/locale 下,可通过@univerjs/sheets-table-ui/locale/en-US这类子路径导入。 - 插件类型是 Sheet:
UniverSheetsTableUIPlugin的type为UniverInstanceType.UNIVER_SHEET(见 src/plugin.ts),即该插件只作用于电子表格实例,不会影响文档或幻灯片。
插件的依赖关系
从 src/plugin.ts 的@DependentOn装饰器可以看到,注册该插件前必须已经注册以下插件:
@DependentOn( UniverRenderEnginePlugin, // 渲染引擎 UniverSheetsPlugin, // 电子表格核心 UniverSheetsTablePlugin, // 表格核心模型 UniverSheetsUIPlugin // 电子表格 UI 基础 ) export class UniverSheetsTableUIPlugin extends Plugin因此一个完整的初始化顺序大致为:UniverSheetsPlugin→UniverSheetsUIPlugin→UniverSheetsTablePlugin→UniverSheetsTableUIPlugin,渲染引擎插件则需先行或同时注册。
插件生命周期:onStarting / onReady / onRendered
UniverSheetsTableUIPlugin在三个生命周期钩子中完成了核心装配(见 src/plugin.ts):
- onStarting:向注入器注册
ComponentsController(并立即实例化)、SheetsTableComponentController、SheetsTableUiService、SheetTableMenuController、SheetTableThemeUIController、SheetTableSelectionController等依赖。 - onReady:通过
touchDependencies实例化上述依赖,确保控制器和服务的副作用(事件订阅、命令监听)生效。 - onRendered:
_registerRenderModules()向渲染管理器注册渲染模块:- 当配置项
hideAnchor !== true时注册SheetTableControlsRenderController(表格锚点控件渲染); - 无条件注册
SheetsTableFilterButtonRenderController(筛选按钮渲染)与SheetsTableRenderController(表格区域渲染)。
- 当配置项
此外,构造函数中通过_initRegisterCommand()注册了两个操作命令:OpenTableFilterPanelOperation与OpenTableSelectorOperation(详见下文「命令与流程」)。
插件配置项
该插件支持通过univer.registerPlugin(UniverSheetsTableUIPlugin, { ... })的第二个参数传入配置。配置类型与默认值定义在 src/config/config.ts:
export interface IUniverSheetsTableUIConfig { anchorHeight?: number; anchorBackgroundColor?: string; hideAnchor?: boolean; menu?: MenuConfig; } export const defaultPluginConfig: IUniverSheetsTableUIConfig = { anchorHeight: 24, anchorBackgroundColor: 'rgb(134,139,156)', };各配置项说明如下:
| 配置项 | 类型 | 默认值 | 作用 |
|---|---|---|---|
anchorHeight | number | 24 | 表格锚点(插入/调整表格范围的悬浮控件)的高度(像素) |
anchorBackgroundColor | string | rgb(134,139,156) | 表格锚点的背景色 |
hideAnchor | boolean | undefined(不隐藏) | 设为true时隐藏锚点控件,此时 src/plugin.ts 的_registerRenderModules()将不再注册SheetTableControlsRenderController |
menu | MenuConfig | 无 | 自定义菜单项配置,会通过configService.setConfig('menu', menu, { merge: true })合并进全局菜单配置 |
插件构造函数对配置的处理方式是:将传入配置与defaultPluginConfig做深合并,menu部分单独合并进全局menu配置,其余部分以SHEETS_TABLE_UI_PLUGIN_CONFIG_KEY('sheets-table-ui.config')为键写入配置服务。
示例:
univer.registerPlugin(UniverSheetsTableUIPlugin, { anchorHeight: 32, anchorBackgroundColor: '#8B8F9C', hideAnchor: false, });命令与交互流程
UI 插件的核心价值体现在两个操作命令上,二者都在 src/plugin.ts 中注册,对应命令定义在 src/commands/operations 目录。
OpenTableSelectorOperation:插入表格(选择范围)
定义于 open-table-selector.operation.ts,命令 ID 为sheet.operation.open-table-selector。它的执行流程是:
- 通过
getSheetCommandTarget获取当前工作簿与工作表; - 取当前最后一次选区
SheetsSelectionsService.getCurrentLastSelection();若为空则回退到A1单格; - 若是单格选区,则调用
expandToContinuousRange(range, { up: true, left: true, right: true, down: true }, worksheet)向四周扩展到连续数据区域,作为默认的表格范围; - 调用
openRangeSelector()打开表格范围选择对话框(TABLE_SELECTOR_DIALOG,宽 300,可拖拽、无遮罩); - 用户确认后,通过
AddSheetTableCommand(来自@univerjs/sheets-table)真正创建表格。
这段逻辑把「选区 → 范围推断 → 范围确认 → 建表」串成了完整的插入表格流程。其中openRangeSelector基于IDialogService打开对话框,并通过onConfirm/onCancel/onClose三个回调把选择结果以 Promise 形式返回给调用方。
OpenTableFilterPanelOperation:打开筛选面板
定义于 open-table-filter-dialog.opration.ts,命令 ID 为sheet.operation.open-table-filter-panel。它接收参数:
export interface IOpenTableFilterPanelOperationParams { row: number; col: number; unitId: string; subUnitId: string; tableId: string; }执行时通过TableManager.getTable(unitId, tableId)校验表格存在,然后委托给SheetsTableComponentController.openOrToggleFilterPanel()打开或切换筛选面板。
筛选面板的开合机制
SheetsTableComponentController(见 src/controllers/sheet-table-component.controller.ts)用上下文键SHEETS_TABLE_FILTER_PANEL_OPENED_KEY管理面板状态:
- 面板已打开且点击的是同一个筛选按钮 → 关闭面板;
- 面板已打开但点击的是其他列 → 先销毁旧的浮层,再打开新的;
- 面板未打开 → 置上下文为已打开,面板由
_initUIPopup()中订阅subscribeContextValue$的回调创建(基于SheetCanvasPopManagerService的浮层)。
这种「上下文键 + RxJS 订阅」的模式,与 Univer 其他 UI 浮层(如筛选、数据验证面板)保持一致,属于可复用的交互范式。
UI 组件层
视图组件集中在 src/views/components 目录,主要包括:
| 组件 | 职责 |
|---|---|
SheetTableSelector | 表格范围选择器(插入表格时选择区域) |
SheetTableFilterPanel | 筛选主面板 |
SheetTableConditionPanel | 条件筛选面板(数值/文本条件) |
SheetTableItemsFilterPanel | 按项(值)筛选面板,支持勾选与计数 |
SheetTableRenameDialog | 表格重命名对话框 |
SheetTableThemePanel | 表格主题(配色)面板 |
SheetTableMenu | 表格上下文菜单 |
配套的 src/views/widgets 目录提供渲染层形状:table-controls.shape.ts(表格锚点控件形状)、table-filter-button.shape.ts(表头筛选按钮形状)、drawings.ts、icons.ts等,负责在 canvas 渲染层绘制交互元素。
服务层:筛选数据聚合
SheetsTableUiService(见 src/services/sheets-table-ui.service.ts)是 UI 层与表格模型之间的桥梁,负责:
- 缓存筛选项:以
tableId + columnIndex为键缓存每列的候选值列表(_itemsCache),并在两种情况下主动失效:- 单元格值被修改(监听
SetRangeValuesMutation)且与某个表格范围相交时,删除对应列的缓存; - 表格筛选条件被设置(监听
SetSheetTableFilterCommand)时,清空该工作表内所有表格的整行缓存。
- 单元格值被修改(监听
- 聚合候选值:
getTableFilterItems()遍历表格过滤范围的所有行,跳过其他列已过滤掉的行,统计当前列的取值分布(itemsCountMap)与总数(allItemsCount),空值显示为本地化的「(空白)」文案(sheets-table-ui.condition.empty)。 - 读写筛选条件:
getTableFilterCheckedItems()读取手动筛选的勾选项,setTableFilter()通过SetSheetTableFilterCommand写入筛选条件。
这套缓存 + 事件失效机制保证了筛选面板在大量数据下不会重复扫描全表,同时数据一变立刻刷新候选列表。
菜单集成
菜单定义与控制器位于 src/menu 目录,index.ts导出了SheetsTableUIMenuSchema(menuSchema),你可以按需把它合并到自定义菜单配置中。菜单工厂函数包括:
- 工具栏插入按钮:
sheetTableToolbarInsertMenuFactory——TableIcon图标、tooltip/标题为sheets-table-ui.title,点击触发OpenTableSelectorOperation(即插入表格);通过getCurrentRangeDisable$在非法选区(如整个工作表被选中)时自动禁用。 - 右键菜单:
SheetTableInsertContextMenuFactory/SheetTableRemoveContextMenuFactory提供「插入行/列」「删除行/列」子菜单,分别绑定SheetTableInsertRowCommand、SheetTableInsertColCommand、SheetTableRemoveRowCommand、SheetTableRemoveColCommand(均来自@univerjs/sheets-table),并用hidden$按当前上下文(是否位于表头、是否在表格内)动态显隐。
渲染控制器
渲染相关的控制器位于 src/controllers,通过IRenderManagerService.registerRenderModule注册到电子表格渲染单元:
SheetsTableRenderController:绘制表格区域(表头、行列边框、斑马纹等)。SheetTableControlsRenderController:绘制表格锚点控件(拖拽调整表格范围),受hideAnchor配置控制。SheetsTableFilterButtonRenderController:绘制表头筛选按钮,点击触发OpenTableFilterPanelOperation。SheetTableSelectionController:处理表格内的选区交互(如整行整列选择)。SheetTableThemeUIController:管理表格主题的 UI 呈现。
每个控制器都有对应的单元测试(见 src/controllers/tests),例如sheet-table-controls-render.controller.spec.ts、sheet-table-filter-button-render.controller.spec.ts,可作为理解渲染行为的参考。
与表格核心层的配合
需要强调的是,UI 层本身不维护表格数据,所有数据操作最终都落到@univerjs/sheets-table:
- 建表:
AddSheetTableCommand - 筛选:
SetSheetTableFilterCommand、SheetTableService - 行列操作:
SheetTableInsertRowCommand/SheetTableInsertColCommand/SheetTableRemoveRowCommand/SheetTableRemoveColCommand - 表格元数据:
TableManager(getTable/getTablesBySubunitId)
从源码结构看,@univerjs/sheets-table-ui通过依赖注入(@Inject(TableManager)、@Inject(SheetTableService))直接消费这些能力,并补充了面板、菜单、控件与本地化文案。因此在集成排错时,如果 UI 行为异常,应先确认底层@univerjs/sheets-table插件已正确注册。
小结
@univerjs/sheets-table-ui为 Univer Sheets 补齐了结构化表格的完整交互闭环:从「插入表格(范围选择)」到「筛选面板(条件/按项)」「行列表头右键操作」「主题与锚点控件」,并以插件生命周期、命令服务、上下文面板、渲染模块和缓存服务五层结构组织代码。接入时只需遵循 README 的三步(安装、导入 CSS、注册插件并合并 Locale),再按需通过配置项与菜单 Schema 定制行为即可。
【免费下载链接】univerUniver is a full-stack framework for creating and editing spreadsheets / word processor / presentation on both web and server.项目地址: https://gitcode.com/GitHub_Trending/un/univer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考