一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情。
ES6 装饰器
ES6 提案里谈到装饰器(Decorator),其是一个函数,用于修改类和类方法的函数。写成@ + 函数名
。
类的装饰
function isDecorator(target) {
target.isTest = true;
}
@isDecorator
class myExample {}
console.log(myExample.isDecorator) // true
以上代码,@isDecorator 是一个装饰器,修改了 myExample 类的行为,并增加了一个 isTest 静态属性。装饰器 isDecorator 的参数 taget 就是被装饰的类 myExample 本身。
方法的装饰
class MyExample {
@readonly
getInfo() { return `${this.name}, ${this.age}` }
}
function readonly(target, name, descriptor){
// ......
}
上面代码中,装饰器readonly
用来装饰“类”的getInfo
方法。装饰器函数 readonly 有三个参数,第一个参数是所装饰的目标对象,第二个参数是所要装饰的属性名,第三个参数是该属性的描述对象。
Nest 装饰器
ES2016
装饰器是一个表达式,它返回一个可以将目标、名称和属性描述符作为参数的函数。可以为类、方法或属性定义装饰器。
内置装饰器
Nest 是基于 装饰器这种特性进行创建的。所以其提供了很多内置的装饰器
- 核心类:@Controller、 @ Injectable 、@UseInterceptors、@UsePipes等等
- Http 类:@Request(),@Req()、@Request(),@Req()
- 模块类:@Global、@Module
Nest 支持自定义装饰器
首先,createParamDecorator 方法创建一个装饰器
export const UserDecorator = createParamDecorator((data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return request.user;
});
使用 createParamDecorator 创建装饰器时,可以通过 data 参数将参数传递给装饰器。
创建后就可以直接使用,且其允许在任何地方使用
@Get()
async findOne(@UserDecorator() user: UserEntity) {
console.log(user);
}
使用管道
将管道应用到自定义装饰器上
@Get()
async findOne(@User(new ValidationPipe()) user: UserEntity) {
console.log(user);
}
装饰器聚合
Nest 提供了一种聚合多个装饰器的方法 applyDecorators,就可以将一系列的行为装饰到你的类、方法或属性上面
export function Auth(...roles: Role[]) {
return applyDecorators(
SetMetadata('roles', roles),
UseGuards(AuthGuard, RolesGuard),
ApiBearerAuth(),
ApiUnauthorizedResponse({ description: 'Unauthorized"' })
);
}
主要是用的是 applyDecorators方法自定义出一个聚合的装饰器。当让一个类也是支持有多个装饰器,执行顺序将按顺序执行
@Get('users')
@Auth('admin')
@UserDecorator()
findAllUsers() {}
通过使用装饰器可以增加某类的特性,也可以将公共抽离出来当作装饰器。
可使用场景:
- 传入参数类型。
- 对返回值的排序、过滤。
- 对某功能进行节流、防抖或其他的功能性代码。
- 一些函数逻辑本身无关的、重复性的代码抽离出来。