路由器 Router

使用路由拆分您的应用程序。

使用 h3 路由器允许使用更高级、更方便的路由系统,例如参数和 HTTP 方法,而 app 实例 本身仅允许静态前缀匹配。

!NOTE 在内部,h3 使用 unjs/radix3 进行路由匹配。

用法

首先,您需要使用 createRouter 实用程序创建一个路由器并将其添加到应用程序堆栈。

js
import { createApp, createRouter, defineEventHandler } from 'h3'

const app = createApp()
const router = createRouter()
app.use(router)

然后,您可以使用名称为 HTTP 方法的方法将路由注册到路由器:

js
router.get(
  '/hello',
  defineEventHandler((event) => {
    return 'Hello world!'
  }),
)

在此示例中,我们为 GET 方法注册路由。这意味着事件处理程序将仅针对 /hello 路由的 GET 请求进行调用。如果您尝试发送 POST 或请求到 /hello/world,则不会调用事件处理程序。

!NOTE 您仍然可以使用 use 将事件处理程序注册到路由器。它将针对每个 HTTP 方法进行调用。

这意味着您可以使用不同的方法为同一路由注册多个事件处理程序:

js
router
  .get(
    '/hello',
    defineEventHandler((event) => {
      return 'GET Hello world!'
    }),
  )
  .post(
    '/hello',
    defineEventHandler((event) => {
      return 'POST Hello world!'
    }),
  )

路由参数

您可以使用 : 前缀在路由中定义参数:

js
router.get(
  '/hello/:name',
  defineEventHandler((event) => {
    return `Hello ${event.context.params.name}!`
  }),
)

在此示例中,name 参数将在 event.context.params 对象中可用。

如果您向 /hello/world 发送请求,事件处理程序将返回 Hello world!

!NOTE 您可以在路由中使用任意数量的参数。

通配符匹配器

除了命名参数,您还可以使用 * 表示未命名的参数

js
router.get(
  '/hello/*',
  defineEventHandler((event) => {
    return `Hello ${event.context.params._}!`
  }),
)

这将匹配 /hello 和子路由,例如 /hello/world/hello/123。但它只会匹配一级子路由。

您可以使用 event.context.params._ 访问通配符内容,其中 _ 是包含通配符内容的字符串。

如果需要匹配多级子路由,可以使用 ** 前缀:

js
router.get(
  '/hello/**',
  defineEventHandler((event) => {
    return `Hello ${event.context.params._}!`
  }),
)

这将匹配 /hello/hello/world/hello/123/hello/world/123 等。

!NOTE 参数 _ 将把完整的通配符内容存储为单个字符串。

嵌套路由器

您可以嵌套路由器以创建路由器树。这对于将您的应用程序拆分为多个部分(如 API 和网站)很有用。

js
import { createApp, createRouter, defineEventHandler, useBase } from 'h3'

export const app = createApp()

const websiteRouter = createRouter().get(
  '/',
  defineEventHandler((event) => {
    return 'Hello world!'
  }),
)

const apiRouter = createRouter().get(
  '/hello',
  defineEventHandler((event) => {
    return 'Hello API!'
  }),
)

websiteRouter.use('/api/**', useBase('/api', apiRouter.handler))

app.use(websiteRouter)

我们创建两个路由器。第一个称为 websiteRouter,是主路由器。第二个,我们创建第二个路由器,称为 apiRouter

然后,我们使用 use 和通配符将 apiRouter 连接到 websiteRouter,以确保每个以 /api 开头的路由和 HTTP 方法都将由 apiRouter 处理。

!NOTE 不要忘记使用 .handler 从路由器获取事件处理程序。

useBase 用于向路由器的每个路由添加前缀。在此示例中,我们向 apiRouter 的每个路由添加 /api 前缀。因此,路由 /hello 将是 /api/hello

最后,我们将 websiteRouter 注册到 app 实例。