SuperAPI AI 工具集

univer-plugin-dev

编程与开发

查看项目

更新于 10-15 20:21

技能介绍

用途

本技能用于指导为 Univer(电子表格/文档/演示引擎)开发自定义插件,扩展 Univer 的功能。适用于编写插件、注册命令/变更/操作、扩展 Facade 等场景。

兼容性

本技能针对 Univer v0.21.x 编写。核心插件模式(生命周期、依赖注入、命令)保持稳定,但具体服务令牌和 Facade 类可能变化。当用户现有代码库模式与示例不同时,优先采用用户代码库的模式。

快速开始

脚手架生成新插件

使用捆绑脚本生成最小插件骨架:

# 如果安装到 ~/.codex/skills/
npx tsx ~/.codex/skills/univer-plugin-dev/scripts/scaffold-plugin.ts my-plugin --path ./src/plugins

# 或直接从本仓库运行
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'; // 用于 Facade 扩展的副作用导入

univer.registerPlugin(MyPlugin);

核心概念

插件生命周期

插件继承自 Plugin 并重写生命周期钩子:

钩子 时机 应做的事
onStarting() 插件挂载,尚无业务单元 注册命令、服务、菜单、快捷键
onReady() 业务单元已创建 访问工作簿/文档实例
onRendered() UI 已渲染 依赖 DOM 的初始化
onSteady() 一切稳定 后台任务

始终使用 disposeWithMe() 注册可释放资源,以便插件销毁时自动清理。

命令系统

三种命令类型:

  • COMMAND — 业务入口。编排变更和操作。若手动推入 IUndoRedoService,则支持撤销/重做。
  • MUTATION — 原子数据变更。持久化到快照。自动可撤销。
  • OPERATION — UI 状态变更。不持久化。不可撤销。

各类型的完整示例及撤销/重做构造见 references/command-system.md。

依赖注入

Univer 使用自定义 DI 容器(Injector)。服务获取方式:

// 构造函数注入
@Inject(IMenuManagerService) private readonly _menuService: IMenuManagerService

// 访问器注入(在命令处理器中)
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 {
    // 实现
    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) => {
    // 业务逻辑
    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、撤销/重做、变更工厂、自定义变更
  • 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 — 生成新插件骨架