Skip to content

扩展框架

AdonisJS 的架构使得扩展框架变得非常容易。我们使用框架的核心 API 来构建一流的第一方包生态系统。

在本指南中,我们将探索你可以使用的不同 API,通过包或在应用程序代码库中扩展框架。

宏和 getter

宏和 getter 提供了一个 API,用于向类的原型添加属性。你可以将它们视为 Object.defineProperty 的语法糖。在底层,我们使用 macroable 包,你可以参考其 README 以获得深入的技术解释。

由于宏和 getter 是在运行时添加的,你需要使用声明合并来告知 TypeScript 添加属性的类型信息。

你可以将添加宏的代码写在专用文件中(如 extensions.ts),并在服务提供者的 boot 方法中导入它。

ts
// title: providers/app_provider.ts
export default class AppProvider {
  async boot() {
    await import('../src/extensions.js')
  }
}

在下面的例子中,我们向 Request 类添加 wantsJSON 方法,同时定义其类型。

ts
// title: src/extensions.ts
import { Request } from '@adonisjs/core/http'

Request.macro('wantsJSON', function (this: Request) {
  const firstType = this.types()[0]
  if (!firstType) {
    return false
  }
  
  return firstType.includes('/json') || firstType.includes('+json')
})
ts
// title: src/extensions.ts
declare module '@adonisjs/core/http' {
  interface Request {
    wantsJSON(): boolean
  }
}
  • declare module 调用期间的模块路径必须与你用于导入类的路径相同。
  • interface 名称必须与你要添加宏或 getter 的类名相同。

Getter

Getter 是添加到类的延迟求值属性。你可以使用 Class.getter 方法添加 getter。第一个参数是 getter 名称,第二个参数是计算属性值的回调函数。

Getter 回调不能是异步的,因为 JavaScript 中的 getter 不能是异步的。

ts
import { Request } from '@adonisjs/core/http'

Request.getter('hasRequestId', function (this: Request) {
  return this.header('x-request-id')
})

// 你可以按如下方式使用该属性。
if (ctx.request.hasRequestId) {
}

Getter 可以是单例,这意味着计算 getter 值的函数只会被调用一次,返回值会在类的实例中缓存。

ts
const isSingleton = true

Request.getter('hasRequestId', function (this: Request) {
  return this.header('x-request-id')
}, isSingleton)

可宏化的类

以下是可以使用宏和 getter 扩展的类列表。

导入路径
Application@adonisjs/core/app
Request@adonisjs/core/http
Response@adonisjs/core/http
HttpContext@adonisjs/core/http
Route@adonisjs/core/http
RouteGroup@adonisjs/core/http
RouteResource@adonisjs/core/http
BriskRoute@adonisjs/core/http
ExceptionHandler@adonisjs/core/http
MultipartFile@adonisjs/core/bodyparser

扩展模块

大多数 AdonisJS 模块提供可扩展的 API 来注册自定义实现。以下是相关列表的汇总。