Skip to content

事件系统

EditorHost 内置类型安全的事件总线,插件和用户代码都可以通过 host.on() / host.off() / host.emit() 发布和订阅事件。

事件监听与移除

typescript
import type { ElementEventData } from 'vkedit'

// 具名函数监听(推荐)
const onElementAdded = (data: ElementEventData) => {
  console.log('新增元素:', data.element.id, data.element.type)
}
host.on('element:added', onElementAdded)

// 移除监听(传入同一函数引用)
host.off('element:added', onElementAdded)

避免内存泄漏

永远不要使用匿名函数监听事件,否则无法精确移除。在 Vue 组件的 onUnmounted 中必须移除所有事件监听。

事件回调参数

所有事件回调接收一个 payload 对象(而非裸参数)。payload 包含事件特定字段和公共字段:

公共字段类型说明
timestampnumber事件时间戳
sourcestring事件来源(插件名或命令名)

例如 element:added 的 payload 类型为 ElementEventData

typescript
interface ElementEventData {
  element: IGraphicElement  // 元素实例
  elementId: string         // 元素 ID
  timestamp?: number
  source?: string
}

完整事件列表

元素事件

事件名Payload 类型触发时机
element:addedElementEventData元素添加到画布
element:removedElementEventData元素从画布删除
element:transformedTransformEventData元素位置/尺寸/旋转变化
element:updatedElementUpdateEventData元素属性更新
element:copiedElementEventData元素被复制
element:pastedElementEventData元素被粘贴
element:clonedElementEventData元素被克隆(Alt 拖拽)
element:registeredElementRegisteredEventData元素类型注册
element:unregisteredElementRegisteredEventData元素类型注销

选择事件

事件名Payload 类型触发时机
selection:changedSelectionEventData选中元素集合变化(包括清空选择时触发,payload 中 selection 为空数组)

SelectionEventData 包含 selection: IGraphicElement[] 字段。

舞台事件

事件名Payload 类型触发时机
stage:mousedownStageMouseEventData画布鼠标按下
stage:mousemoveStageMouseEventData画布鼠标移动
stage:mouseupStageMouseEventData画布鼠标释放
stage:clickStageMouseEventData画布点击
stage:dblclickStageDblClickEventData画布双击
stage:contextmenuStageMouseEventData右键菜单
stage:wheelStageMouseEventData鼠标滚轮
stage:keydownStageKeyboardEventData键盘按下
stage:keydown-deleteStageKeyboardEventDataDelete 键
stage:keydown-left/right/up/downStageKeyboardEventData方向键

命令历史事件

事件名Payload 类型触发时机
command:executedCommandEventData命令执行
command:undoneCommandEventData命令撤销
command:redoneCommandEventData命令重做

CommandEventData 包含 command 字段,可通过 data.command.constructor.name 获取命令名称。

视图事件

事件名Payload 类型触发时机
view:snap-changeViewEventData吸附开关切换

缩放与平移监听

view:zoom-changeview:panview:grid-visibility-change 等事件目前在类型中定义但尚未实际触发。如需监听缩放变化,请监听 host:status-changed 事件并检查 status.zoom 是否变化。

状态事件

事件名Payload 类型触发时机
host:status-changedStatusEventData画布状态变化(尺寸、DPM、缩放等)
plugin:registeredPluginEventData插件注册
plugin:unregisteredPluginEventData插件注销

导入导出事件

事件名Payload 类型触发时机
export:startExportEventData导出开始
export:completeExportEventData导出完成
export:errorExportEventData导出失败
import:startImportEventData导入开始
import:completeImportEventData导入完成
import:errorImportEventData导入失败
preview:startPreviewEventData预览开始
preview:completePreviewEventData预览完成

Vue 集成示例

vue
<script setup lang="ts">
import { createEditorHost, type SelectionEventData } from 'vkedit'
import { ref, onMounted, onUnmounted } from 'vue'

const host = createEditorHost()
const selectedCount = ref(0)

const onSelectionChanged = (data: SelectionEventData) => {
  selectedCount.value = data.selection.length
}

onMounted(() => {
  host.on('selection:changed', onSelectionChanged)
})

onUnmounted(() => {
  host.off('selection:changed', onSelectionChanged)
})
</script>

自定义事件

插件可以发布自定义事件。建议使用 EventUtils.createCustomEvent() 生成事件名:

typescript
import { EventUtils, BasePlugin } from 'vkedit'

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

  protected onInstall(): void {
    // 发布自定义事件
    const eventName = EventUtils.createCustomEvent('my-plugin', 'done')
    this.host.emit(eventName as any, { result: 'success', timestamp: Date.now(), source: 'my-plugin' })
  }
}

事件命名规范

自定义事件使用 custom:插件名:动作 格式(由 EventUtils.createCustomEvent 生成),与内置事件保持区分。

下一步

基于 MIT 许可发布