装饰器类型
类装饰器
类装饰器在类声明之前声明,应用于类的构造函数,可以用来观察、修改或替换类定义
类装饰器的 target 参数是类的构造函数,可以修改类的原型或添加静态属性:
function ClassDecorator(target: Function) {
// target 是类的构造函数
console.log('ClassDecorator called on', target);
// 可以修改类的原型
target.prototype.customProperty = 'custom value';
}
@ClassDecorator
class MyClass {
constructor() {}
}
const instance = new MyClass();
console.log(instance.customProperty); // 输出: custom value输出结果:
ClassDecorator called on [class MyClass]
custom value
instance.customProperty: custom value方法装饰器
方法装饰器应用于方法的属性描述符,可以用来修改方法的行为或添加元数据
方法装饰器接收三个参数:类的原型对象、方法名和属性描述符:
function MethodDecorator(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor,
) {
console.log('方法装饰器被调用');
console.log('target:', target); // 原型对象
console.log('propertyKey:', propertyKey); // 方法名
console.log('descriptor:', descriptor); // 属性描述符
// 可以修改方法行为
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log('方法执行前');
const result = originalMethod.apply(this, args);
console.log('方法执行后');
return result;
};
}
class Example {
@MethodDecorator
public greet(message: string): void {
console.log(`Hello, ${message}!`);
}
}输出结果:
方法装饰器被调用
target: {}
propertyKey: greet
descriptor: {
value: [Function: greet],
writable: true,
enumerable: false,
configurable: true
}属性装饰器
属性装饰器应用于类的属性,可以用来定义属性的元数据或修改属性的行为
属性装饰器接收两个参数:类的原型对象和属性名:
function PropertyDecorator(target: any, propertyKey: string) {
console.log('属性装饰器被调用');
console.log('target:', target); // 原型对象
console.log('propertyKey:', propertyKey); // 属性名
}
class Example {
@PropertyDecorator
public name: string = 'test';
}输出结果:
属性装饰器被调用
target: {}
propertyKey: name参数装饰器
参数装饰器应用于方法或构造函数的参数,可以用来定义参数的元数据
参数装饰器接收三个参数:类的原型对象、方法名和参数索引:
function ParameterDecorator(
target: any,
propertyKey: string | undefined,
parameterIndex: number,
) {
console.log('参数装饰器被调用');
console.log('target:', target); // 原型对象或构造函数
console.log('propertyKey:', propertyKey); // 方法名,构造函数参数为undefined
console.log('parameterIndex:', parameterIndex); // 参数索引
}
class Example {
public greet(@ParameterDecorator message: string): void {
console.log(`Hello, ${message}!`);
}
constructor(@ParameterDecorator public id: number) {}
}输出结果:
参数装饰器被调用
target: {}
propertyKey: greet
parameterIndex: 0
参数装饰器被调用
target: [class Example]
propertyKey: undefined
parameterIndex: 0访问器装饰器
访问器装饰器应用于 getter 或 setter,可以用来修改访问器的行为
访问器装饰器接收三个参数:类的原型对象、访问器名和属性描述符:
function AccessorDecorator(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor,
) {
console.log('访问器装饰器被调用');
console.log('target:', target);
console.log('propertyKey:', propertyKey);
console.log('descriptor:', descriptor);
}
class Example {
private _age: number = 0;
@AccessorDecorator
get age(): number {
return this._age;
}
set age(value: number) {
this._age = value;
}
}输出结果:
访问器装饰器被调用
target: {}
propertyKey: age
descriptor: {
get: [Function: get age],
set: [Function: set age],
enumerable: false,
configurable: true
}有参装饰器
有参装饰器(装饰器工厂)是一个返回装饰器函数的函数,可以自定义装饰器的行为
有参装饰器允许我们传递参数来配置装饰器的行为:
function ClassDecoratorWithParams(param: string) {
return function(target: Function) {
console.log('ClassDecoratorWithParams called with', param);
target.prototype.param = param;
};
}
@ClassDecoratorWithParams('Hello')
class MyClass {
constructor() {}
}
const instance = new MyClass();
console.log(instance.param); // 输出: Hello输出结果:
ClassDecoratorWithParams called with Hello
Hello装饰器的执行顺序
装饰器的执行顺序遵循严格的规则:从内到外、从下到上的层级结构
执行顺序规则
实例成员:
首先应用参数装饰器
然后应用方法、访问器或属性装饰器
静态成员:
首先应用参数装饰器
然后应用方法、访问器或属性装饰器
构造函数:
应用参数装饰器
类:
最后应用类装饰器
代码示例验证
@ClassDecorator
class Example {
constructor(@ParameterDecorator public id: number) {
console.log('构造函数被调用');
}
@PropertyDecorator
public name: string = 'test';
private _age: number = 0;
@AccessorDecorator
get age(): number {
return this._age;
}
set age(value: number) {
this._age = value;
}
@MethodDecorator
public greet(@ParameterDecorator message: string): void {
console.log(`Hello, ${message}!`);
}
}输出结果:
属性装饰器被调用
target: {}
propertyKey: name
访问器装饰器被调用
target: {}
propertyKey: age
descriptor: { get: [Function: get age], set: [Function: set age], enumerable: false, configurable: true }
参数装饰器被调用
target: {}
propertyKey: greet
parameterIndex: 0
方法装饰器被调用
target: {}
propertyKey: greet
descriptor: { value: [Function: greet], writable: true, enumerable: false, configurable: true }
参数装饰器被调用
target: [class Example]
propertyKey: undefined
parameterIndex: 0
类装饰器被调用
target: [class Example]执行顺序解析
从输出结果可以看出,装饰器的执行顺序是:
属性装饰器:修饰
name属性访问器装饰器:修饰
age访问器方法参数装饰器:修饰
greet方法的参数方法装饰器:修饰
greet方法构造函数参数装饰器:修饰构造函数的参数
类装饰器:修饰整个类
Nestjs的装饰器
Nestjs 提供了一些内置的装饰器,用于简化开发过程。装饰器的名称以 @ 开头,例如 @Controller、@Get、@Post 等。框架内部会根据装饰器的类型和位置,自动应用相应的行为。主要的有参装饰器基于Reflect-metadata模块实现。
控制器装饰器
控制器装饰器用于标记一个类作为控制器,处理 HTTP 请求
控制器装饰器可以指定控制器的基础路径:
import { Controller } from '@nestjs/common';
@Controller('users')
export class UsersController {
// 控制器方法
}参数说明:
path(可选):控制器的基础路径,所有路由都会基于这个路径
路由装饰器
路由装饰器用于定义 HTTP 请求的处理方法,包括 @Get、@Post、@Put、@Delete 等
@Get 装饰器
import { Controller, Get } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get()
findAll() {
return 'This action returns all users';
}
@Get(':id')
findOne(@Param('id') id: string) {
return `This action returns a #${id} user`;
}
}@Post 装饰器
import { Controller, Post } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Post()
create() {
return 'This action adds a new user';
}
}其他路由装饰器
@Put():处理 PUT 请求@Delete():处理 DELETE 请求@Patch():处理 PATCH 请求@Options():处理 OPTIONS 请求@Head():处理 HEAD 请求
依赖注入装饰器
依赖注入装饰器用于标记可注入的服务和注入依赖项
@Injectable 装饰器
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
findAll() {
return ['user1', 'user2'];
}
}@Inject 装饰器
import { Injectable, Inject } from '@nestjs/common';
@Injectable()
export class UsersService {
constructor(
@Inject('DATABASE_CONNECTION') private databaseConnection: any
) {}
}模块装饰器
模块装饰器用于组织应用程序的结构,定义模块的控制器、提供者和依赖关系
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
@Module({
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService]
})
export class UsersModule {}参数说明:
controllers:模块中包含的控制器
providers:模块中包含的提供者(服务)
exports:模块导出的提供者,供其他模块使用
imports:模块依赖的其他模块
实现一个Nestjs @Get 装饰器
import axios from 'axios';
const Get = (url: string): MethodDecorator => {
// 有参装饰器实质是通过高阶函数实现的
return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
const func = descriptor.value;
axios
.get(url)
.then((res: any) => {
func(res.data, { success: true });
})
.catch((err: any) => {
func({}, { success: false });
});
};
};
class Controller {
@Get('https://jsonplaceholder.typicode.com/users')
getList(list: any[], { success }: { success: boolean }) {
console.log(list);
return list;
}
}实现一个Get装饰器,用于从指定的URL获取数据并返回给调用者,返回结果如下:
[
{
id: 1,
name: "Leanne Graham",
username: "Bret",
email: "Sincere@april.biz",
address: {
street: "Kulas Light",
suite: "Apt. 556",
city: "Gwenborough",
zipcode: "92998-3874",
geo: { lat: "-37.3159", lng: "81.1496" }
},
phone: "1-770-736-8031 x56442",
website: "hildegard.org",
company: {
name: "Romaguera-Crona",
catchPhrase: "Multi-layered client-server neural-net",
bs: "harness real-time e-markets"
}
},
...
]总结
装饰器是 Nestjs 中用于定义应用程序行为的元数据机制,它们可以在类、方法、属性、参数、访问器等位置应用,以实现自定义的行为和功能。
Nestjs-装饰器
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。



评论交流
欢迎留下你的想法