TypeScript 入门学习(六):TypeScript 装饰器

Typescript 装饰器

装饰器是一种特殊类型的声明,它可以被附加到类声明,方法,属性或参数上,可以修改类的行为。通俗的讲,装饰器就是一个方法,可以注入到类、方法、属性、参数上来扩展类、方法、属性、参数的功能。

常见装饰器:类装饰器、方法装饰器、属性装饰器、参数装饰器。

装饰器写法:普通装饰器(不可传参)、装饰器工厂(可传参)。

类装饰器

类装饰器在类声明之前声明,应用于构造函数,可以用来监视、修改或替换类定义。类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数。如果装饰器返回一个值,它会使用提供的构造函数来替换类的声明。

普通装饰器

/**
 * 装饰器
 * target:代表当前修饰的类
 */
function logClass(target: any) {
  console.log(target);
  
  target.prototype.data = 'dataChange';
}


@logClass
class Operator {
  data: string | undefined;
  constructor() {
  }

  getData(): any {
    console.log('data:', this.data);
  }
}

const operator = new Operator();
operator.getData(); // dataChange
console.log(operator.data); // dataChange

装饰器工厂

/**
 * params:类装饰器传入的参数
 * target:当前修饰的类 
 */
function logClass(params: string) {

  return function (target: any) {
    console.log('params:', params);
    console.log(target);
    target.prototype.data = params; 
  }

}

@logClass('hello')
class Operator {

  data: string | undefined;

  constructor() {
  }

  getData(): any {
    console.log('data:', this.data);
  }
}

const operator = new Operator();

console.log(operator.data); // hello

方法装饰器

方法装饰器会被应用到方法的描述上,可以用来监视、修改或替换方法定义。
方法装饰器会在运行时传入下列 3 个参数:

  1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象;
  2. 方法名字;
  3. 方法的属性描述。
function logMethod(param: any) {

  return function (target: any, methodName: any, desc: any) {
    console.log(target);
    console.log(methodName); // getData
    console.log(desc.value);
    // 修改装饰器方法,将方法里的参数变成 string 类型
    var method = desc.value;
    desc.value = function (...args: any[]) {
      args = args.map(value => {
        return String(value);
      });
      method.apply(this, args);
    }
  }
}

class Operator {

  data: string | undefined;

  constructor() {
  }

  @logMethod('new hello world')
  getData(...args: any[]): any {
    console.log(args);
  }
}

const operator = new Operator();
operator.getData(123, 'aaa'); // ['123', 'aaa']

属性装饰器

属性装饰器表达式会在运行时当作函数被调用,传入 2 个参数:

  1. 对静态成员来说是类的构造函数,对于实例成员是类的原型对象;
  2. 属性名字。
// 属性装饰器
function logProperty(param: any) {

  return function (target: any, propertyName: any) {
    console.log(target);
    console.log(propertyName);
    target[propertyName] = param;
  }
}


class Operator {

  @logProperty('hello world')
  data: string | undefined;

  constructor() {
  }
  
  getData(): any {
    console.log('data:', this.data);
  }
}

const operator = new Operator();
operator.getData(); // hello world
console.log(operator.data); // hello world

参数装饰器

参数装饰器表达式会在运行时当作函数被跳跃,可以使用参数装饰器为类的原型增加一些元素数据,传入下列 3 个参数:

  1. 对静态成员来说是类的构造函数,对于实例成员是类的原型对象;
  2. 方法的名称;
  3. 参数在函数参数列表中的索引。
// 参数装饰器
function logParam(param: any) {
  return function(target: any, methodName: any, index: any) {
    console.log(param);
    console.log(target);
    console.log(methodName); // getData
    console.log(index); // 0
  }
}

class Operator {

  data: string | undefined;

  constructor() {
  }

  getData(@logParam('arg') arg: any): any {
    console.log(arg);
  }
}

const operator = new Operator();
operator.getData('aaa');

装饰器执行顺序

属性装饰器>方法装饰器>参数装饰器>类装饰器

如果有多个同类型的装饰器,则执行顺序是从后到前执行。

发布了89 篇原创文章 · 获赞 79 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/oschina_41790905/article/details/100569456