typescript 装饰器 Decorator

69 阅读1分钟

装饰器:一种特殊类型声明,它能够被附加到类声明,方法,访问符,属性,参数上

定义一个类装饰器 他会把class Http的构造函数传入Base函数当作第一个参数 使用:@函数名

const Base: ClassDecorator = (target) => {
  target.prototype.name = "新增的姓名";
  target.prototype.fn = () => {
    console.log("新增的方法");
  };
};
@Base
class Http {}
const http = new Http() as any;
http.fn();
console.log(http.name);

属性装饰器 PropertyDecorator

参数装饰器 ParameterDecorator

方法装饰器 MethodDecorator

import axios from "axios";
import "reflect-metadata";
const Base = (name: string) => {
  const fn: ClassDecorator = (target) => {
    target.prototype.name = name;
    target.prototype.fn = () => {
      console.log("新增的方法");
    };
  };
  return fn;
};
const Get = (url: string) => {
  /**
   *
   * @param target
   * @param key 方法名称getList
   * @param descriptor {
                          "writable": true,
                          "enumerable": false,
                          "configurable": true,
                          value:f getList(data)
                        }
   */
  const fn: MethodDecorator = (target, key, descriptor: PropertyDescriptor) => {
    const keyWord = Reflect.getMetadata("keyWord", target);
    const keyWordList = Reflect.getMetadata("keyWordList", target);
    axios.get(url).then((res) => {
      descriptor.value(
        keyWord
          ? keyWordList
            ? res.data[keyWord][keyWordList]
            : res.data[keyWord]
          : res.data
      );
    });
  };
  return fn;
};
const Result = () => {
  /**
   *
   * @param target
   * @param key 方法名称getList
   * @param index 参数位置 0
   */
  const fn: ParameterDecorator = (target, key, index) => {
    Reflect.defineMetadata("keyWord", "result", target);
  };
  return fn;
};
const List = () => {
  const fn: ParameterDecorator = (target) => {
    Reflect.defineMetadata("keyWordList", "list", target);
  };
  return fn;
};
@Base("zhangsan")
class Http {
  @Get("https://api.apiopen.top/api/getHaoKanVideo?page=0&size=20") //方法装饰器
  getList(@Result() @List() data: any) {
    // console.log(data.result.list); //没加属性装饰器这样才能拿到list
    console.log(data); //添加@Result()后就可以直接拿result 添加@Result()与@List()list
  }
}
const http = new Http() as any;

装饰器工厂:使用函数柯里化实现

const Base = (name: string) => {
  const fn: ClassDecorator = (target) => {
    target.prototype.name = name;
    target.prototype.fn = () => {
      console.log("新增的方法");
    };
  };
  return fn;
};
@Base("zhangsan")
class Http {}
const http = new Http() as any;
http.fn();
console.log(http.name);