Skip to content

自定义插件开发

vkedit 的插件架构允许你开发自定义插件,扩展编辑器功能。

BasePlugin 基类

所有插件继承自 BasePlugin。子类必须实现 nameversion 抽象属性,可选重写生命周期钩子:

typescript
import { BasePlugin } from 'vkedit'

class MyPlugin extends BasePlugin {
  public name = 'my-plugin'
  public version = '1.0.0'

  protected onInstall(): void {
    // 注册工具栏按钮、绑定事件等
    // 可通过 this.host 访问 EditorHost
  }

  protected onUninstall(): void {
    // 清理资源、移除事件监听
  }
}

必填属性

nameversion 是抽象属性,必须实现。name 使用 kebab-case 命名(如 'my-plugin')。

注册工具栏按钮

工具栏按钮通过 tool:registered 事件注册,render 返回一个 Vue 组件:

typescript
import { BasePlugin } from 'vkedit'
import MyTool from './MyTool.vue'

class MyPlugin extends BasePlugin {
  public name = 'my-plugin'
  public version = '1.0.0'

  protected onInstall(): void {
    // 注册工具栏按钮
    this.host.emit('tool:registered', {
      toolName: 'my-tool',
      render: () => MyTool,
      group: 'tools',
      source: 'my-plugin',
      timestamp: Date.now(),
    })
  }

  protected onUninstall(): void {
    // ToolbarManagerPlugin 会自动管理注册的按钮
  }
}

group 可选值为 'tools'(工具组,默认)、'actions'(操作组)、'history'(历史组)。

注册图形工具

如果要添加自定义可绘制图形,需注册四种组件:图形工具按钮、图形渲染组件、属性面板、元素构造器:

typescript
protected onInstall(): void {
  // 1. 注册图形工具按钮(工具箱中显示)
  this.host.emit('graphic-tool:registered', {
    type: 'my-shape',
    render: () => MyTool,
    source: 'my-plugin',
    timestamp: Date.now(),
  })

  // 2. 注册图形渲染组件(画布上渲染)
  this.host.emit('graphic:registered', {
    type: 'my-shape',
    render: () => MyShape,
    source: 'my-plugin',
    timestamp: Date.now(),
  })

  // 3. 注册属性面板
  this.host.emit('property-panel:registered', {
    graphicTypes: ['my-shape'],
    render: () => MyPropertyPanel,
    isCanvas: false,
    isPublic: false,
    source: 'my-plugin',
    timestamp: Date.now(),
  })

  // 4. 注册元素构造器(用于 createElement 和反序列化)
  this.host.emit('element:registered', {
    type: 'my-shape',
    createElement: () => new MyElement(this.host),
    source: 'my-plugin',
    timestamp: Date.now(),
  })
}

监听事件

typescript
import type { SelectionEventData } from 'vkedit'

class MyPlugin extends BasePlugin {
  public name = 'my-plugin'
  public version = '1.0.0'

  private handler = (data: SelectionEventData) => {
    if (data.selection.some((e) => e.type === 'rect')) {
      console.log('矩形被选中')
    }
  }

  protected onInstall(): void {
    this.host.on('selection:changed', this.handler)
  }

  protected onUninstall(): void {
    this.host.off('selection:changed', this.handler)
  }
}

使用箭头函数或 bind

事件监听器必须使用箭头函数属性或 .bind(this),以确保 this 指向插件实例。移除时也必须传入同一函数引用。

安装自定义插件

typescript
host.installPlugin('my-plugin', MyPlugin)

扩展类型系统

通过模块声明合并,可为插件和元素类型添加类型推断:

typescript
// 在插件文件中声明
declare module '@/types' {
  interface PluginMap {
    'my-plugin': MyPlugin
  }
  interface ElementTypeMap {
    'my-shape': MyElement
  }
}

声明后,host.getPlugin('my-plugin') 会自动推断返回 MyPlugin 类型,elementManager.createElement('my-shape') 会推断返回 MyElement 类型。

下一步

基于 MIT 许可发布