基于类的扩展
如果您的扩展要监听多个事件并跟踪状态,您可能需要考虑将扩展定义为 JavaScript 类。类是创建对象的模板。它封装了数据和对数据进行操作的方法。这种封装有助于使扩展更有条理。我们面临的挑战是如何定义一个类,使其可以作为 Antora 扩展使用。本页将向您展示如何做到这一点。
扩展类结构
基于类的扩展的基本结构如下:
-
定义一个以扩展命名的类(如 MyExtension)
-
添加一个 Antora 可以调用的静态注册方法
-
将监听器定义为实例方法(例如
onPlaybookBuilt ({ playbook })
) -
添加一个构造函数,接受生成器上下文并从类中注册监听器
-
导出类定义
下面是我们扩展类的骨架:
class MyExtension {
}
让我们来补充一下细节。
注册方法和初始化
Antora 不会为您的类创建实例,但您可以使用类的静态注册方法来创建实例。如果您来自 Java,可以把它想象成类的主方法。下面是该入口点的样子:
class MyExtension {
static register () {
new MyExtension(this)
}
}
module.exports = MyExtension
Antora 将看到的只是导出类定义中的 register 方法,Antora 将调用该方法启动进程。其余工作都在扩展实例中进行。
请注意静态 register 方法是如何将我们从静态函数过渡到扩展类实例的。register 方法将生成器上下文传递给了扩展类的构造函数,这样构造函数就可以访问并存储对生成器上下文的引用。
监听器方法
监听器被定义为扩展类的方法。它们会像其他监听器函数一样被调用,只是会同时引用类的当前实例(this
)和生成器上下文(this.context
)。这样,它们就可以访问扩展的属性(扩展状态)和生成器中的上下文变量。下面是以方法形式定义监听器的扩展类:
class MyExtension {
static register () {
new MyExtension(this)
}
onPlaybookBuilt () {
this.startTime = +new Date
}
onSitePublished () {
const elapsed = (+new Date - this.startTime) / 1000
const logger = this.context.getLogger('my-extension')
logger.info(`elapsed time: ${elapsed}s`)
}
}
module.exports = MyExtension
现在只需将这些监听器连接到事件即可。
构造器和增加监听器
下一步是创建一个构造函数,接受生成器上下文并添加监听器。下面是带有构造函数的扩展类:
class MyExtension {
static register () {
new MyExtension(this)
}
constructor (generatorContext) {
;(this.context = generatorContext)
.on('playbookBuilt', this.onPlaybookBuilt.bind(this))
.on('sitePublished', this.onSitePublished.bind(this))
}
onPlaybookBuilt () {
this.startTime = +new Date
}
onSitePublished () {
const elapsed = (+new Date - this.startTime) / 1000
const logger = this.context.getLogger('my-extension')
logger.info(`elapsed time: ${elapsed}s`)
}
}
module.exports = MyExtension
添加每个监听器时,必须将其绑定到扩展实例(即 this
)。否则,监听器将无法访问扩展实例上的属性。监听器仍可使用 context
属性访问生成器上下文,构造函数会将生成器上下文分配给该属性。
正如你所看到的,使用基于类的扩展可以使你的扩展代码更有条理。它还允许你的扩展利用其他面向对象的模式,如继承、组合和委托。