【TypeScript】装饰器 Decorator

装饰器(Decorators)是 TypeScript 中一种特殊的语法,用于在类、方法、属性等元素上附加元数据或修改其行为。装饰器提供了一种在不改变类的定义的情况下,对类进行扩展或修改的方式。

装饰器的使用类似于注解,在代码中以 @ 符号开头,后面紧跟装饰器工厂函数或表达式。装饰器工厂函数会在装饰器被应用到类、方法等上时被调用,它接受不同的参数,具体取决于被装饰的目标。

其实装饰器就是一个可以提前拿到类本身(或原型对象)并预处理的函数。当类定义的时候被调用。

使用装饰器之前,需要先在 tsconfig.json 中开启两个配置:

【TypeScript】装饰器 Decorator_第1张图片

以下是一些常见的装饰器的用法和示例:

  1. 参数装饰器
import axios from 'axios'
// 使用 defineMetadata 需要 npm i reflect-metadata
import 'reflect-metadata'
const Get = (url: string) => {
  // _ 是一个占位符,防止和下面的 key 重名
  const fn: MethodDecorator = (target, _, descriptor: PropertyDescriptor) => {
    // console.log(target, key, descriptor)
    const key = Reflect.getMetadata('key',target)
    axios.get(url).then(res => {
      descriptor.value(key ? res.data[key] : res.data)
    })
  }
  return fn
}
const Result = () => {
  const fn: ParameterDecorator = (target, key, index) => {
    Reflect.defineMetadata('key', 'result', target)
    // console.log(target, key, index) // {} getList 0
  }
  return fn
}
class Http {
  @Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
  // @Result() 参数装饰器
  getList(@Result() data: any) {
    console.log(data);
  }
}
  1. 类装饰器:

    类装饰器用于装饰类的声明。它接受一个参数,即被装饰的类的构造函数。

function logClassName(constructor: Function) {
  console.log(`Class name: ${constructor.name}`);
}

@logClassName
class MyClass {
  // ...
}

// 写成匿名函数形式:
const Base:ClassDecorator = (target) =>{
console.log(target)
target.prototype.xx = 'xx'
target.prototype.fn = () =>{
  console.log('fn')
}
}
@Base
class Http {
// ...
}
const http = new Http() as any
// Base(Http) // 删掉 @Base,写成这样也是可以的
http.fn()
  1. 方法装饰器:

    方法装饰器用于装饰类的方法。它接受三个参数:目标类的原型,方法名称,方法的属性描述符。

function logMethod(target: any, methodName: string, descriptor: PropertyDescriptor) {
  console.log(`Method ${methodName} is decorated.`);
}

class MyComponent {
  @logMethod
  doSomething() {
    // ...
  }
}

// 实例:
import axios from 'axios'
const Get = (url: string) => {
const fn: MethodDecorator = (target, key, descriptor: PropertyDescriptor) => {
  console.log(target, key, descriptor)
  axios.get(url).then(res => {
    descriptor.value(res.data)
  })
}
return fn
}
class Http {
@Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10') 
getList(data: any) {
  console.log(data.result.list)
}
}
  1. 属性装饰器:

    属性装饰器用于装饰类的属性。它接受两个参数:目标类的原型和属性名称。

function readonly(target: any, propertyName: string) {
  Object.defineProperty(target, propertyName, { writable: false });
}

class Person {
  @readonly
  name: string = "Alice";
}
  1. 装饰器工厂:

    装饰器工厂是一个函数,用于生成装饰器。它可以接受参数,用于传递额外的配置信息。

function log(message: string) {
  return function(target: any, propertyName: string) {
    console.log(`Logged message: ${message}`);
  };
}

class Product {
  @log("Product created")
  name: string;
}

需要注意的是,装饰器的执行顺序是从上往下的,即从最外层的装饰器开始执行。装饰器可以叠加在一起,对同一个目标进行多次装饰。

你可能感兴趣的:(TypeScript,typescript,javascript,前端)