基于类的扩展

如果您的扩展要监听多个事件并跟踪状态,您可能希望将您的扩展定义为一个JavaScript类。类是创建对象的模板。它封装了数据和操作该数据的方法。这种封装有助于保持您的扩展更有组织性。挑战在于如何以一种可以用作Antora扩展的方式定义类。本页将向您展示如何做到这一点。

扩展类结构

基于类的扩展的基本结构如下:

  • 定义一个以您的扩展命名的类(例如,MyExtension)

  • 添加一个静态的register方法,Antora可以调用

  • 将监听器定义为实例方法(例如,onPlaybookBuilt ({ playbook })

  • 添加一个接受生成器上下文并从类中注册监听器的构造函数

  • 导出类定义

这是我们扩展类的框架:

class MyExtension {
}

让我们填写细节。

register方法和实例化

Antora不会创建您的类的实例,但您可以使用类上的静态register方法来实现。如果您熟悉Java,您可以将其视为类的主方法。以下是入口点的外观:

class MyExtension {
  static register () {
    new MyExtension(this)
  }
}

module.exports = MyExtension

Antora将只看到导出类定义上的register方法,并调用它以启动进程。其余的工作发生在扩展实例中。

请注意,静态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属性访问生成器上下文,构造函数将生成器上下文分配给该属性。

正如您所见,使用基于类的扩展可以使您的扩展代码更有组织性。它还允许您的扩展利用其他面向对象的模式,如继承、组合和委托。