Skip to content

事件系统

字数
1177 字
阅读时间
5 分钟

在上一节中,我们已经了解了插件的基本结构和注册方式。接下来,我们将深入了解 IPE 的事件系统。

事件系统在 IPE 中扮演着底层的角色,事件系统允许插件之间进行通信和协作。它支持监听运行状态的生命周期事件和提供扩展性的自定义事件。

基本用法

让我们先从一个基本示例开始:

ts
ctx
.
on
('quick-edit/wiki-page', (
payload
) => {
const {
wikiPage
} =
payload
console
.
log
('当前正在编辑的页面是:',
wikiPage
.
title
)
})

上述代码片段实现了一个简单的功能:当“快速编辑”插件加载了页面数据后,控制台会输出当前正在编辑的页面标题。

如你所见,ctx.on() 方法监听了一个事件。传入的第一个参数 quick-edit/wiki-page 是事件的名称,而第二个参数则是事件的回调函数。每一次 quick-edit/wiki-page 事件被触发 (即用户进入快速编辑模式,页面数据加载完成) 时都会调用该函数。

事件与会话构成了最基础的交互模型。你在监听器中不仅能够打印控制台消息,还能够像写普通网页脚本一样处理更复杂的事务,例如:

ts
ctx.plugin({
  name: 'wiki-editor',
  apply(ctx) {
    ctx.on('quick-edit/wiki-page', async (payload) => {
      const { wikiPage, modal } = payload
      const $content = modal.get$content()
      if (wikiPage.title.includes('兽耳娘')) {
        $content.prepend('好好好!')
      }
    })
  },
})

监听事件

聪明的你应该不难发现,这一套 API 非常像 Node.js 的 EventEmitter:第一个参数表示要监听的事件名称,第二个参数表示事件的回调函数。

这套事件系统与 EventEmitter 的一个不同点在于,无论是 ctx.on() 还是 ctx.once() 都会返回一个 dispose 函数,调用这个函数即可取消注册监听器。因此你其实不必使用 ctx.once()ctx.off()。下面给一个只触发一次的监听器的例子:

ts
const 
dispose
=
ctx
.
on
('foo', (
payload
) => {
console
.
log
('只会触发一次')
dispose
() // 取消注册
})

事件的命名

IPE 的事件名字可以是任意字符串,不过官方插件的事件名称一般遵循 插件ID/事件名称 的命名规范。

我们也推荐这样做,因为这样可以避免事件名称冲突,并且让事件的来源一目了然。

触发事件

如果你开发的插件希望允许其他插件扩展,那么触发事件就是相当合适的手段。

触发事件的基本用法也都与 EventEmitter 类似,第一个参数是事件名称,之后的参数对应回调函数的参数。下面是一个例子:

ts
ctx
.
emit
('custom-event',
arg1
,
arg2
, ...
rest
)
// 对应于
ctx
.
on
('custom-event', (
arg1
,
arg2
, ...
rest
) => {})

触发方式

IPE 的事件系统与 EventEmitter 的另一个区别在于,触发一个事件可以有着多种形式,目前支持 4 个不同的方法,足以适应绝大多数需求。

  • emit: 同时触发所有 event 事件的回调函数
  • parallel: 上述方法对应的异步版本
  • bail: 依次触发所有 event 事件的回调函数;当返回一个 false, null, undefined 以外的值时将这个值作为结果返回
  • serial: 上述方法对应的异步版本

声明自定义事件

当然,定义事件的类型不是必须的,如果你只是想要开发一些简单的自用插件,完全不必如此大费周章。除非你有强迫症。

对于 TypeScript 开发者来说,你可以通过声明模块的方式,为事件添加类型定义:

ts
interface SomeEventPayload {
  
foo
: string
bar
: number
} declare module '@inpageedit/core' { interface
Events
{
'my-plugin/some-event'(
payload
: SomeEventPayload): void
} }
ctx
.
on
('my-plugin/some-event', (
payload
) => {
console
.
log
(
payload
.
foo
)
})

这样其它开发者即使不去看文档或者读源码,也能通过类型推导,对事件的参数有一个大概的认识。


再比如,你想要监听另一个插件提供的事件,请记得在文件头部导入类型声明:

ts
import type {} from 'inpageedit-plugin-foo' // 引入类型定义

// 如果没有上面的类型导入,下面的代码爆类型错误
ctx.on('foo/someEvent', (payload) => {})

贡献者

暂无相关贡献者

✏️ InPageEdit NEXT