Skip to content
此页目录
本文总阅读量

TypeScript 装饰器

开启装饰器需要在tsconfig.jsonjsconfig.json中开启

json
"experimentalDecorators": true

类装饰器

普通装饰器(不能传参)

ts
function myDestroyed(params: any) {
  console.log(params); // params 就是当前类
  params.prototype.age = 123;
}

@myDestroyed
class Person {
  public name: string = "tom";
}

console.log(new Person()); // {name:'tom', prototype: {age: 123}}

装饰器工厂(可以传参)

ts
function myDestroyed(params: any) {
  console.log(params); // params 是传入的参数
  return function (target:any){
    console.log(target); // target 就是当前类
    target.prototype.age = target;
  }
}

@myDestroyed(123)
class Person {
  public name: string = "tom";
}

console.log(new Person()); // {name:'tom', prototype: {age: 123}}

重载构造函数

ts
function logClass(target: any) {
  console.log(target);
  return class extends target {
    apiUrl: any = "修改后的数据";
  };
}

@logClass
class HttpClient {
  public apiUrl: string= "构造函数里面的apiUrl";
}

console.log(new HttpClient().apiUrl); // '修改后的数据'

属性装饰器

ts
function logProperty(params:any){
  console.log(params); // 333 params是传入的参数
  return function(target:any,attr:any){
      console.log(target); // 当前类
      console.log(attr); // url 属性名
      target[attr]=params;
  }
}
class HttpClient{
  
  @logProperty('333')
  public url:any;

}
console.log(new HttpClient().url); // 333

方法装饰器

ts
function get(params: any) {
  return function (target: any, methodName: any, desc: any) {
    console.log(params); // 传入的参数
    console.log(target); // 当前类
    console.log(methodName); // getData 方法名
    console.log(desc); // 描述符 { configurable:true enumerable:false value:ƒ getData() writable:true }
    
    target.apiUrl = "xxxx"; // 添加到原型上
    target.run = function () { // 添加到原型上
      console.log("run");
    };
  };
}

class HttpClient {
  public url: any | undefined;
  @get("传入的参数")
  getData() {
    console.log(this.url);
  }
}

var http: any = new HttpClient();

修改装饰器方法

ts
function get(params: any) {
  return function (target: any, methodName: any, desc: any) {
    console.log(params); // 传入的参数
    console.log(target); // 当前类
    console.log(methodName); // getData 方法名
    console.log(desc); // 描述符 { configurable:true enumerable:false value:ƒ getData() writable:true }
    
    const getData = desc.value; // 保存当前方法
    desc.value = function (...arr:number[]){
      // 做一些操作
      const list: string[] = arr.map(item => String(item))

      // 调用类的getData
      getData.call(this,...list)
    }

  };
}

class HttpClient {
  @get("传入的参数")
  getData(...arr:number[]) {
    console.log(arr,'我是getData');
  }
}

var http: any = new HttpClient();
http.getData([1,2,3]) // ['1,2,3'] '我是getData'

属性装饰器

ts
function get(params: any) {
  return function (target: any, methodName: any, index: any) {
    console.log(params); // 传入的参数
    console.log(target); // 当前类
    console.log(methodName); // getData 方法名
    console.log(index); // 0 参数的下标
  };
}

class HttpClient {
  getData(@get("传入的参数")arr:number[]) {
    console.log(arr,'我是getData');
  }
}

var http: any = new HttpClient();

装饰器执行顺序

  1. 属性 > 方法 > 方法参数 > 类
  2. 如果有多个同样的装饰器,它会先执行后面的
ts
@logClass1('api')
@logClass2('xxxx')
class HttpClient{
  @logAttribute1()
  @logAttribute2()
  public apiUrl:string | undefined;
  constructor(){
  }

  @logMethod1()
  @logMethod2()
  getData(){
      return true;
  }

  setData(@logParams1() attr1:any,@logParams2() attr2:any,){

  }
}

/* 
  属性装饰器2
  属性装饰器1
  方法装饰器2
  方法装饰器1
  方法参数装饰器2
  方法参数装饰器1
  类装饰器2
  类装饰器1
*/

var http:any=new HttpClient();

function logClass1(params:string){
  return function(target:any){
    console.log('类装饰器1')
  }
}

function logClass2(params:string){
  return function(target:any){
    console.log('类装饰器2')
  }
}

function logAttribute1(params?:string){
  return function(target:any,attrName:any){
    console.log('属性装饰器1')
  }
}

function logAttribute2(params?:string){
  return function(target:any,attrName:any){
    console.log('属性装饰器2')
  }
}

function logMethod1(params?:string){
  return function(target:any,attrName:any,desc:any){
    console.log('方法装饰器1')
  }
}
function logMethod2(params?:string){
  return function(target:any,attrName:any,desc:any){
    console.log('方法装饰器2')
  }
}



function logParams1(params?:string){
  return function(target:any,attrName:any,desc:any){
    console.log('方法参数装饰器1')
  }
}

function logParams2(params?:string){
  return function(target:any,attrName:any,desc:any){
    console.log('方法参数装饰器2')
  }
}

评论

交流群