Nest:自定义装饰器

自定义装饰器的概念

装饰器(Decorator)是 TypeScript 的一个特性,它能够添加额外的声明性逻辑到类、方法、属性、参数上。

自定义装饰器通常用于实现特定的功能,如日志记录、权限验证、数据校验等。创建自定义装饰器主要涉及以下几种类型:

  1. 类装饰器:用于类声明
  2. 方法装饰器:用于方法
  3. 属性装饰器:用于属性
  4. 参数装饰器:用于方法参数

自定义方法装饰器

我们可以自定义装饰器,满足自己需要的功能。

创建 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 组合多个装饰器

以下代码将 GetMyCustomDecoratorUseGuards 三个装饰器合并为一个:

使用:

访问 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,
      });
    }
  };
}

使用这个装饰器来自动为属性赋予默认值:

访问页面:

相关推荐
嘉伟桑1 小时前
Python调用电价API返回JSON示例:分时电价、现货电价和字段解析
后端
刘卓航众创芯云服务部1 小时前
Kimi K3复杂任务实测:我把团队最头疼的三个场景全跑了一遍
前端
cll_8692418911 小时前
一个好看的Wordpress博客文字css样式
前端·css·ui
武子康1 小时前
Shippy:确定性工具、会话级 Sandbox 与 Live-Data Eval(4 类收敛 + 7 步实现方案 + 6 类评测指标)
前端·人工智能·后端
糖果店的幽灵1 小时前
langgraph分支之 - 动态分支(Dynamic Branch)
java·前端·javascript·人工智能·langgraph
meilindehuzi_a1 小时前
Workflow 与 Agent 有什么区别:从 LangChain 流水线到智能体决策
前端·人工智能
三翼鸟数字化技术团队1 小时前
一种前端大屏适配方案
前端·css
我叫黑大帅1 小时前
我为什么单一消费者的场景下,要用 Redis List 当消息队列?
redis·后端·面试
AskHarries2 小时前
文件上传系统
后端
小四的小六2 小时前
WebView 在 AI 时代的三个被低估的价值——从自己的 AI 产品里找到的答案
前端·openai·ai编程