一文了解Nestjs装饰器

最近用nestjs做了一个前后端的全栈项目,在nestjs中看到的装饰器无处不在,今天主要回顾下关于装饰器的那些事

本文主要会从以下几点认识装饰器

  • 装饰器是什么,它解决了什么样的问题
  • 装饰器如何作用在类上
  • 装饰器在方法属性形参上有什么区别

什么是装饰器

decorator中有讲到,装饰器是一种函数,增强JS类的能力,它可以装饰函数,装饰属性,或者装饰类。是通过@fn方式来装饰的。

在使用之前,我们必须开启tsconfig.jsonexperimentalDecorators选项,这样就可以使用装饰器了

json 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "experimentalDecorators": true
  }
}

类上的装饰器

js 复制代码
// index.ts
function test(target: any) {
  console.log(target);
  console.log(new target().name);
}
@test
class Person {
  constructor(public name: string) {
    this.name = "Web技术学苑";
  }
}

执行npx ts-node index.ts 我们会发现,当我在类上使用一个装饰器时,target这个默认的形参就说class Person这个构造函数

所以我在test的装饰器内部去new target()相当于是new Person()

方法上的装饰器

主要这个装饰器会用在方法上,我们会发现@getName装饰器是放在getName上的

js 复制代码
function getName(target: any, key: string, descriptor: any) {
  console.log(target, key, descriptor);
  const fn = descriptor.value;
  console.log(fn()) // Maic
}
class Person {
  constructor(public name: string) {
    this.name = "Web技术学苑";
  }
  @getName
  getName() {
    // return this.name;
    return 'Maic'
  }
}

当我们npx ts-node index.ts时,输出的结果如下

  • target就是一个对象{}
  • key就是getName方法名
  • descriptor包含了一个value的对象值

当我们发现descriptor的value时一个可执行函数时,其实就是getName返回的值

js 复制代码
{} 
getName
{
  value: [Function: getName],
  writable: true,
  enumerable: false,
  configurable: true
}

我们以另外一个具体的例子来感受下,在方法中使用装饰器

自定义装饰器

js 复制代码
function getName(target: any, key: string, descriptor: any) {
  //console.log(target, key, descriptor);
  const fn = descriptor.value;
  const result = fn();
  console.log(result);
}

function Get(url: string) {
  return (target: any, key: string, descriptor: any) => {
    const request = fetch(url);
    const fn = descriptor.value;
    request
      .then((res) => res.json())
      .then((result) => {
        fn.call(target,result);
      });
  };
}
class Person {
  constructor(public name: string) {
    this.name = "Web技术学苑";
  }
  @getName
  getName() {
    return "Maic";
  }
  @Get("https://movie.douban.com/j/search_tags?type=movie&source=index")
  getUserInfo(res: any) {
    console.log(res);
  }
}

运行npx ts-node index.ts

所以我们通过自定义装饰器@Get('xxx')达到了我们想要的效果,注意在@Get中是接收了一个参数,然后在Get中返回了一个函数

  • Get中有形参
  • 返回了一个函数
  • 在返回的函数的三个参数依次是targetkey, descriptor 其中target{},keygetUserInfo,descriptor是一个可枚举对象

Get方法中并没有返回,而是通过回调的方式将结果输出了,所以一个简单的路由装饰器Get方法就已经完成了,这在nestjs中非常的常用,你会看到很多诸如GetPost的装饰器。

函数形参上的装饰器

装饰器也可以用在形参上,因此我们定义了一个@userParams,不过此时装饰器的中的target是一个对象,key是当前函数名,第三个参数是当前形参的索引

js 复制代码
function userParams(target: any, key: string, index: number) {
  console.log(target, key, index, "===");
}

class Person {
  constructor(public name: string, public useInfo: any) {
    this.name = "Web技术学苑";
    this.useInfo = {
      age: 18,
      sex: "男",
    };
  }
  setUseInfo(@userParams params: any = { age: "10" }) {
    return this.name;
  }
}

属性上的装饰器

我们从以下代码中发现,在属性上的装饰器与方法上的形参有所不同,属性装饰器只有两个参数,第一个参数返回一个对象,第二个参数是当前属性名称。

js 复制代码
function getAge(target: any, key: string) {
  console.log(target, "==getAge");
  console.log(key, "=key");
}
class Person {
  @getAge
  public age: number;
  constructor(public name: string, public useInfo: any) {
    this.name = "Web技术学苑";
    this.useInfo = {
      age: 18,
      sex: "男",
    };
    this.age = 18;
  }
}

在关于装饰器的设计中,它帮我们解决了什么样的问题,这点在nestjs中关于装饰器无处不在,在鉴权路由Module等等,使用装饰器,这将极大的抽象了复杂的逻辑,方便我们在业务开发中拿来即用。

最后关于装饰器我们也可以参考这篇文章,学习更多关于装饰器更多内容

总结

  • 了解装饰器的用处,本质上装饰器就是函数,通过@修饰函数变成了装饰器,增强了类的能力,可以修饰属性方法形参

  • 比较了装饰器在方法函数形参属性的不同,通过自定义装饰器@Get深入了解到装饰器在方法上的使用

  • 本文示例code example

相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼4 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax