自定义装饰器的概念
装饰器(Decorator)是 TypeScript 的一个特性,它能够添加额外的声明性逻辑到类、方法、属性、参数上。
自定义装饰器通常用于实现特定的功能,如日志记录、权限验证、数据校验等。创建自定义装饰器主要涉及以下几种类型:
- 类装饰器:用于类声明
- 方法装饰器:用于方法
- 属性装饰器:用于属性
- 参数装饰器:用于方法参数
自定义方法装饰器
我们可以自定义装饰器,满足自己需要的功能。
创建 nest 项目:
bash
nest new custom-decorator -p npm
nest g decorator user --flat
这个函数就是一个自定义装饰器。
添加个 Guard:
bash
nest g guard user --flat --no-spec
获取定义的 set-user 元数据:
在对应的控制器方法应用自定义装饰器和守卫:
访问 http://localhost:3000,控制台打印到了对应设置的元数据:
参数装饰器
bash
nest g decorator getUser --flat
我们可以通过自定义装饰器获取请求中的特定属性:
使用参数装饰器:
控制台打印:
applyDecorators 组合多个装饰器
以下代码将 Get
、MyCustomDecorator
和 UseGuards
三个装饰器合并为一个:
使用:
访问 http://localhost:3000/user,服务端控制台打印:
实现内置的 @Param、@Query、@Headers 装饰器
@MyHeaders:
typescript
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const CustomHeaders = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return data ? request.headers[data.toLowerCase()] : request.headers;
},
);
分别用内置 Headers 和自己实现的 CustomHeaders:
访问下,控制台打印:
@MyQuery:
typescript
export const CustomQuery = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return data ? request.query[data] : request.query;
},
);
访问页面:
控制打印:
@MyParam:
typescript
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
// 创建自定义的 @Param 装饰器
export const CustomParam = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return data ? request.params[data] : request.params;
},
);
访问页面:
控制台打印:
自定义 class 装饰器
typescript
import { applyDecorators, Controller, SetMetadata } from '@nestjs/common';
export const CustomController = (path, metaData) => {
return applyDecorators(Controller(path), SetMetadata('my-class', metaData));
};
使用:
获取定义 class 上的元数据:
访问 http://localhost:3000/app,控制台打印:
自定义属性装饰器
属性装饰器通常用来处理与类实例相关的逻辑,比如添加额外的验证、格式化数据或者注入依赖。
在这个装饰器中,我们定义了一个新的属性描述符,并使用 Object.defineProperty
重新定义了属性,这样就可以在 getter 和 setter 中添加自定义的逻辑:
typescript
export function DefaultValue(value: string): PropertyDecorator {
return function (target, propertyKey: string | symbol) {
let val = value;
const getter = () => {
return val;
};
const setter = (next: string) => {
val = next;
};
// 删除属性
if (delete target[propertyKey]) {
// 重新定义属性
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter,
enumerable: true,
configurable: true,
});
}
};
}
使用这个装饰器来自动为属性赋予默认值:
访问页面: