关于 univer-plugin-dev
面向 Univer 开发者的插件开发技能,指导扩展 Univer 功能,并针对 v0.21.x 编写。内容涵盖插件生命周期、依赖注入、命令系统、Facade 扩展和界面定制。
主要功能
- 01生成插件骨架
- 02管理插件生命周期与资源清理
- 03注册命令、菜单和快捷键
- 04通过依赖注入获取服务
- 05扩展 Facade 与界面
适用场景
- 01为 Univer 创建自定义插件
- 02添加工具栏按钮和菜单
- 03实现可撤销的数据变更
- 04向 Facade 添加插件能力
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ dream-num/ univer-sdk-skills --skill univer-plugin-dev安装后在 Claude Code 中输入/univer-plugin-dev确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/command-system.mdevent-system.mdfacade-extension.mdplugin-architecture.mdui-customization.mdscripts/scaffold-plugin.ts详细介绍
Univer 插件开发
用于构建自定义插件以扩展 Univer 功能的指南。
兼容性:此技能适用于 Univer
v0.21.x。核心插件模式(生命周期、DI、命令)保持稳定,但具体的服务令牌和 facade 类可能会发生变化。如果用户现有代码库中的模式与此处示例不同,请优先遵循现有模式。
快速开始
搭建新插件
使用随附脚本生成最小化的插件骨架:
# If installed to ~/.codex/skills/
npx tsx ~/.codex/skills/univer-plugin-dev/scripts/scaffold-plugin.ts my-plugin --path ./src/plugins
# Or from this repo directly
npx tsx ~/univer-sdk-skills/skills/univer-plugin-dev/scripts/scaffold-plugin.ts my-plugin --path ./src/plugins
这会创建:
my-plugin/
├── src/
│ ├── index.ts
│ ├── plugin.ts
│ ├── commands/
│ │ └── commands.my-command.ts
│ ├── controllers/
│ │ └── my-menu.controller.ts
│ └── facade/
│ └── f-univer.ts
├── package.json
└── tsconfig.json
在应用中注册插件
import { MyPlugin } from './plugins/my-plugin/src';
import './plugins/my-plugin/src/facade/f-univer'; // side-effect import for Facade extension
univer.registerPlugin(MyPlugin);
核心概念
插件生命周期
插件继承自 Plugin,并重写生命周期钩子:
| 钩子 | 时机 | 操作 |
|---|---|---|
onStarting() | 插件已挂载,尚无单元 | 注册命令、服务、菜单和快捷键 |
onReady() | 业务单元已创建 | 访问工作簿/文档实例 |
onRendered() | UI 已渲染 | 执行依赖 DOM 的初始化 |
onSteady() | 一切稳定 | 执行后台任务 |
始终使用 disposeWithMe() 注册可释放资源,以便在插件销毁时自动清理。
命令系统
命令分为三种类型:
- COMMAND — 业务入口。负责协调数据变更和操作。若手动将条目推送到
IUndoRedoService,则支持撤销/重做。 - MUTATION — 原子数据变更。会持久化到快照中,并自动支持撤销。
- OPERATION — UI 状态变更。不持久化,也不支持撤销。
每种类型的完整示例以及撤销/重做构造方法,请参阅 references/command-system.md。
依赖注入
Univer 使用自定义 DI 容器(Injector)。通过以下方式获取服务:
// Constructor injection
@Inject(IMenuManagerService) private readonly _menuService: IMenuManagerService
// Accessor injection (in command handlers)
const service = accessor.get(IMenuManagerService);
常见服务令牌:
ICommandService— 注册/执行命令IMenuManagerService— 添加菜单/工具栏项目IShortcutService— 注册键盘快捷键IContextMenuService— 上下文菜单ComponentManager— 注册 React 组件/图标IUniverInstanceService— 获取当前工作簿/文档/幻灯片IUndoRedoService— 推送撤销/重做条目
Facade 扩展
扩展 Facade 类,向最终用户提供插件功能:
import { FWorksheet } from '@univerjs/sheets/facade';
class FWorksheetMyMixin extends FWorksheet {
myMethod(): this {
// implementation
return this;
}
}
FWorksheet.extend(FWorksheetMyMixin);
declare module '@univerjs/sheets/facade' {
interface FWorksheet extends FWorksheetMyMixin {}
}
常见任务
完整示例(子菜单、上下文菜单、Range Popup、组件替换、工具栏 + 命令 + 快捷键的完整流程),请参阅 references/ui-customization.md。
添加工具栏按钮
this._menuManagerService.mergeMenu({
[RibbonOthersGroup.OTHERS]: {
['my-button']: {
order: 10,
menuItemFactory: () => ({
id: 'my-button',
title: 'My Button',
type: MenuItemType.BUTTON,
}),
},
},
});
注册命令
const MyCommand: ICommand = {
id: 'my.command.id',
type: CommandType.COMMAND,
handler: (accessor) => {
// business logic
return true;
},
};
this._commandService.registerCommand(MyCommand);
扩展 Facade
class FWorksheetMyMixin extends FWorksheet {
myMethod(): this { return this; }
}
FWorksheet.extend(FWorksheetMyMixin);
declare module '@univerjs/sheets/facade' {
interface FWorksheet extends FWorksheetMyMixin {}
}
参考资料
- 插件架构:
references/plugin-architecture.md— 生命周期、DI、服务注册、控制器模式 - 命令系统:
references/command-system.md— COMMAND / MUTATION / OPERATION、撤销/重做、mutation 工厂、自定义 mutation - Facade 扩展:
references/facade-extension.md— 扩展 FUniver、FWorkbook、FWorksheet、FRange,以及多个扩展的合并策略 - UI 自定义:
references/ui-customization.md— 菜单、子菜单、快捷键、上下文菜单、弹出窗口、组件替换 - 事件系统:
references/event-system.md— 事件、钩子、自定义事件、RxJS 流
另请参阅 univer-integrate 技能,了解:
- 自定义公式函数(
univer-integrate技能) - 权限(
univer-integrate技能) - 网络层(
univer-integrate技能)
脚本
- 搭建:
scripts/scaffold-plugin.ts— 生成新的插件骨架
评论
支持 Markdown