Skip to content
Our Sponsors
Open in Anthropic

title: 封装 - Elysia 教程 layout: false search: false authors: [] head: - - meta - property: 'og:title' content: 封装 - Elysia 教程

- - meta
  - name: 'description'
    content: Elysia 钩子仅封装到其自身实例。如果您创建新实例,它不会与其他实例共享钩子。

- - meta
  - property: 'og:description'
    content: Elysia 钩子仅封装到其自身实例。如果您创建新实例,它不会与其他实例共享钩子。

封装

Elysia 钩子仅封装到其自身实例。

如果您创建新实例,它不会与其他实例共享钩子。

ts
import { Elysia } from 'elysia'

const profile = new Elysia()
	.onBeforeHandle(
		({ query: { name }, status }) => {
			if(!name)
				return status(401)
		}
	)
	.get('/profile', () => 'Hi!')

new Elysia()
	.use(profile)
	.patch('/rename', () => 'Ok! XD')
	.listen(3000)
localhost

GET

尝试在 URL 栏中将路径更改为 /rename 并查看结果


Elysia 隔离生命周期,除非明确声明。

这类似于 JavaScript 中的 export,您需要导出函数以使其在模块外可用。

要将生命周期**"导出"**到其他实例,您必须添加指定作用域。

作用域

有 3 个可用作用域:

  1. local(默认)- 仅应用于当前实例和后代
  2. scoped - 应用于父级、当前实例和后代
  3. global - 应用于所有应用该插件的实例(所有父级、当前和后代)

在我们的例子中,我们想将登录检查应用到作为直接父级的 app,因此我们可以使用 scopedglobal

ts
import { Elysia } from 'elysia'

const profile = new Elysia()
	.onBeforeHandle(
		{ as: 'scoped' }, 
		({ cookie }) => {
			throwIfNotSignIn(cookie)
		}
	)
	.get('/profile', () => 'Hi there!')

const app = new Elysia()
	.use(profile)
	// 这里有登录检查
	.patch('/rename', ({ body }) => updateProfile(body))
localhost

GET

将生命周期转换为 "scoped" 将将生命周期导出到父实例。 而 "global" 将将生命周期导出到拥有插件的所有实例。

作用域 中了解更多信息。

守卫

类似于生命周期,schema 也封装到其自身实例。

我们可以指定与生命周期类似的作用域。

typescript
import { Elysia } from 'elysia'

const user = new Elysia()
	.guard({
		as: 'scoped', 
		query: t.Object({
			age: t.Number(),
			name: t.Optional(t.String())
		}),
		beforeHandle({ query: { age }, status }) {
			if(age < 18) return status(403)
		}
	})
	.get('/profile', () => 'Hi!')
	.get('/settings', () => 'Settings')

非常重要的一点是,每个钩子都会影响其声明之后的所有路由。

更多信息请参见 作用域

练习

让我们为 nameCheckageCheck 定义一个作用域,使我们的应用程序正常工作。

  1. Name Check

    Make sure that user provides `name` query is applied to **only instance that use plugin** (self, and parent)

  2. Age Check

    Make sure that user is at least 18 years old is applied **all** endpoint

Show answer

我们可以按如下方式修改作用域:

  1. nameCheck 作用域修改为 scoped
  2. ageCheck 作用域修改为 global
typescript
import { Elysia, t } from 'elysia'

const nameCheck = new Elysia()
	.onBeforeHandle(
		{ as: 'scoped' }, 
		({ query: { name }, status }) => {
			if(!name) return status(401)
		}
	)

const ageCheck = new Elysia()
	.guard({
		as: 'global', 
		query: t.Object({
			age: t.Number(),
			name: t.Optional(t.String())
		}),
		beforeHandle({ query: { age }, status }) {
			if(age < 18) return status(403)
		}
	})

const name = new Elysia()
	.use(nameCheck)
	.patch('/rename', () => 'Ok! XD')

const profile = new Elysia()
	.use(ageCheck)
	.use(name)
	.get('/profile', () => 'Hi!')

new Elysia()
	.use(profile)
	.listen(3000)
  • index.ts