Univer 单元格批注核心包 @univerjs/sheets-note 使用与架构深度解析 Univer 单元格批注核心包 univerjs/sheets-note 使用与架构深度解析【免费下载链接】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/univeruniverjs/sheets-note是 Univer 表格Sheets生态中负责单元格批注Note核心模型与命令的插件包为单元格提供增删改查、显隐切换、撤销重做、随行列变更联动以及文档快照序列化等能力。本文以该包的 README 为主线结合 packages/sheets-note 下的真实源码讲解从安装接入、数据模型、命令系统到 Facade API 的完整链路帮助你理解批注功能在 Univer 中如何被组织与扩展。包概览定位与边界根据 README 中的包概览表univerjs/sheets-note的关键属性如下PackageUMD globalCSSLocalesFacade entryuniverjs/sheets-noteUniverSheetsNoteNoNoYes从中可以提炼出三点定位信息纯核心层该包不携带任何 CSS也没有自己的多语言资源Locales说明它只负责批注的数据与逻辑层不渲染任何界面。提供 Facade 入口Facade entry Yes意味着它向 Univer 的 FacadeuniverAPI注入批注相关的 API 与事件方便开发者用简洁的命令式接口操作批注。与 UI 包分工明确README 的 Integration Notes 明确指出需要编辑界面时应搭配univerjs/sheets-note-ui使用——核心包管数据UI 包管交互呈现。安装与版本一致性README 给出的安装方式非常直接pnpm add univerjs/sheets-note # or npm install univerjs/sheets-note同时 README 强调了一条对 Univer 全家桶通用的铁律保持所有univerjs/*包版本一致Keep alluniverjs/*packages on the same version避免因各包版本漂移导致接口不匹配。这一点在 monorepo 工作区pnpm-workspace.yaml和示例工程中均可看到遵循同一版本约束的实践。快速接入注册插件README 展示了最小接入代码import { UniverSheetsNotePlugin } from univerjs/sheets-note; univer.registerPlugin(UniverSheetsNotePlugin);从源码 plugin.ts 可以看出该插件更多细节插件名为SHEET_NOTE_PLUGIN见 const.ts声明为UniverInstanceType.UNIVER_SHEET类型仅服务于表格单元。通过DependentOn(UniverSheetsPlugin)声明依赖univerjs/sheets主包注册时会自动校验并确保表格核心插件已就绪。配置项类型为IUniverSheetsNoteConfig当前在 config/config.ts 中为空接口默认配置defaultPluginConfig为空对象插件配置会以sheets-note.config为 key 写入IConfigService为后续扩展保留入口。插件在onStarting阶段向依赖注入容器注册了 4 个核心依赖并立即实例化前 3 个依赖职责SheetsNoteModel批注内存数据模型与变更事件流SheetsNoteController注册批注相关命令与 mutationSheetsNoteResourceController快照序列化、工作表删除/复制联动SheetsNoteRefRangeController行列插入/删除时批注位置联动onReady阶段实例化数据模型ISheetNote 与 SheetsNoteModel批注的数据结构定义在 sheets-note.model.tsexport interface ISheetNote { id: string; // 批注唯一 ID row: number; // 所在行0 基索引 col: number; // 所在列0 基索引 width: number; // 批注展示宽度 height: number; // 批注展示高度 note: string; // 批注文本内容 show?: boolean; // 是否显示控制弹出/收起 }SheetsNoteModel是批注的唯一数据源采用三级Map结构组织数据unitId工作簿→ subUnitId工作表→ noteId → ISheetNote。围绕它提供了一组完整操作 APIupdateNote(unitId, subUnitId, row, col, note, silent?)新建或更新批注。若没有传入id会用generateRandomId(6)自动生成 6 位随机 ID。removeNote(...)按noteId或(row, col)删除批注。toggleNotePopup(...)切换批注的show状态用于弹出/收起气泡。updateNotePosition(...)将批注移动到新的(newRow, newCol)。getNote(...)按 ID 或行列坐标查询单条批注getSheetNotes(...)、getUnitNotes(...)、getNotes()分别按工作表、工作簿、全量维度取数。模型还对外暴露了基于 RxJS 的响应式流change$全部变更、getSheetShowNotes$(unitId, subUnitId)某工作表所有处于显示状态的批注以及getCellNoteChange$(unitId, subUnitId, row, col)某单元格批注的变更。所有变更都会发出ISheetNoteChange其中type: update表示常规更新type: ref表示因引用范围变化而移动位置——这两种类型正是 Facade 事件与 UI 重绘的输入源。命令与撤销重做Command/Mutation 双层设计与 Univer 整体架构一致批注的写操作遵循Command → Mutation → Model的调用链Command 负责业务意图与撤销栈管理Mutation 负责真正落地到 Model。相关实现位于 note.command.ts 与 note.mutation.ts。三条业务命令命令ID行为SheetUpdateNoteCommandsheet.command.update-note更新/新建批注接受{ unitId, sheetId, row, col, note }参数SheetDeleteNoteCommandsheet.command.delete-note删除当前选中单元格的批注SheetToggleNotePopupCommandsheet.command.toggle-note-popup显示/隐藏当前选中单元格批注的气泡四个底层 MutationMutationID作用UpdateNoteMutationsheet.mutation.update-note落库更新/新建RemoveNoteMutationsheet.mutation.remove-note落库删除ToggleNotePopupMutationsheet.mutation.toggle-note-popup落库切换显示状态UpdateNotePositionMutationsheet.mutation.update-note-position落库移动位置以SheetUpdateNoteCommand为例其 handler 会先通过getSheetCommandTarget解析当前命令作用的工作簿与工作表取旧批注构造 redo/undo 的 mutation 对用commandService.syncExecuteCommand同步执行 redo mutation成功后通过undoRedoService.pushUndoRedo入栈。注意一个细节若旧批注存在undo 用UpdateNoteMutation还原若不存在即纯新建undo 则用RemoveNoteMutation兜底删除。而SheetDeleteNoteCommand中删除命令的 redo 只携带noteId说明按 ID 删除即可精准定位无需行列坐标。所有命令都在 sheets.note.controller.ts 中统一注册进ICommandService。与工作表操作的联动资源快照与拦截器批注要能随文档保存、随工作表删除而清理、随工作表复制而复制靠的是 sheets-note-resource.controller.ts 的两个机制1. 插件资源快照Snapshots。控制器通过IResourceManagerService.registerPluginResource注册名为SHEET_NOTE_PLUGIN的资源处理器toJson把当前工作簿的全部批注序列化为{ sheetId: { row: { col: note } } }结构的 JSONparseJson反向解析onLoad时逐条回填到 ModelonUnLoad时清空该工作簿的批注缓存。这让批注得以参与 Univer 统一的文档快照/加载流程。2. 工作表命令拦截Intercept。控制器通过SheetInterceptorService.interceptCommand监听两条命令RemoveSheetCommand删除工作表为被删除工作表上的每条批注追加一个RemoveNoteMutationredo和对应的UpdateNoteMutationundo实现删除工作表时自动清理批注且可撤销。CopySheetCommand复制工作表为源表的每条批注生成一份拷贝写入目标表并用generateRandomId(6)生成新 ID 避免与源批注冲突undo 时逐条移除。行列变更时的位置联动RefRange 控制器当用户插入/删除行或列时批注必须跟随单元格一起移动否则会出现批注挂在旧坐标的错误。这一职责由 sheets-note-ref-range.controller.ts 承担它基于univerjs/sheets提供的RefRangeService监听范围变化对每个批注坐标注册 watcher当引用范围变化后若单元格仍存在resultRange有效生成UpdateNotePositionMutation把批注移动到新的(startRow, startColumn)若目标范围消失如整行删除导致批注所在单元格被移除则生成RemoveNoteMutation删除批注undo 中保留UpdateNoteMutation以便恢复。这套机制与表格自身的引用范围ref-range联动逻辑复用同一基础设施保证批注在行/列增删场景下的数据一致性。Facade API 与事件面向二次开发者的入口univerjs/sheets-note提供两处 Facade 扩展1. 工作表级查询 API。在 f-worksheet.ts 中通过 mixin 为FWorksheet增加getNotes()方法返回当前工作表全部批注数组。README 对应的官方示例思路如下const fWorkbook univerAPI.getActiveWorkbook(); const fWorksheet fWorkbook.getSheetByName(Sheet1); if (!fWorksheet) return; const notes fWorksheet.getNotes(); notes.forEach((item) { const { row, col, note } item; console.log(Cell ${fWorksheet.getRange(row, col).getA1Notation()} has a note: ${note}); });2. 命令级事件钩子。在 f-univer.ts 中FUniverSheetsNoteMixin基于model.change$与commandService.beforeCommandExecuted双向打通事件系统注册了成对的前置Before与后置事件事件类别事件新增BeforeSheetNoteAdd/SheetNoteAdd更新BeforeSheetNoteUpdate/SheetNoteUpdate删除BeforeSheetNoteDelete/SheetNoteDelete显示BeforeSheetNoteShow/SheetNoteShow隐藏BeforeSheetNoteHide/SheetNoteHide前置事件支持可取消语义当监听器触发fireEvent返回 true 时抛出CanceledError中断命令执行例如在BeforeSheetNoteAdd中拦截非法内容的写入。后置事件则携带workbook、worksheet、row、col、note/oldNote等完整上下文供业务方做审计、同步或自定义展示逻辑。与 sheets-note-ui 的分工协作如 README 的 Integration Notes 所述univerjs/sheets-note应与univerjs/sheets-note-ui搭配使用以提供编辑 UI。二者关系可概括为核心包定义ISheetNote数据结构、SheetsNoteModel模型、命令/mutation、快照序列化、ref-range 联动与 Facade 事件——这是批注能力的大脑。UI 包负责批注气泡的渲染、编辑框、右键菜单入口、快捷键绑定等交互层——这是批注的手脚通过消费核心包的命令与事件流实现界面与数据的同步。即使只注册核心包批注的数据能力命令、撤销重做、保存恢复、行列联动依然完整可用这为需要自研批注界面的团队提供了干净的扩展基座。测试保障包内 src 各目录均配有单元测试可作为理解行为契约的补充材料模型层有 sheets-note.model.spec.ts命令层有 note.command.spec.ts控制器层有 sheets-note-resource.controller.spec.ts 与 ref-range.controller.spec.tsFacade 层有 sheets-note.facade.spec.ts覆盖了从数据读写到命令撤销、资源快照、范围联动与 API 事件的全链路行为。小结univerjs/sheets-note以小而专的方式解决了表格批注的核心数据问题SheetsNoteModel提供内存模型与响应式事件Command/Mutation 双层命令体系保证可撤销重做资源控制器让批注随文档保存与工作表增删联动ref-range 控制器应对行列变更Facade 层则向业务侧暴露简洁的 API 与可取消事件。理解这一分层无论是直接接入批注功能还是在其基础上构建自定义批注 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创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考