如何在Typescript中编译装饰器(注释)?

时间:2016-01-21 10:42:42

标签: typescript angular

在Angular 2中,我可以创建一个组件,如下所示:

import {Component, Template} from 'angular2/angular2'

@Component({
  selector: 'my-component'
})
@View({
  inline: "<div>Hello my name is {{name}}</div>"
})
export class MyComponent {
  constructor() {
    this.name = 'Max'
  }
  sayMyName() {
    console.log('My name is', this.name)
  }
}

(来源:http://blog.ionic.io/angular-2-series-components/

然后将其编译为常规ES5。

我的问题分为两部分:

  1. 这些装饰器特定于Angular。它们是如何定义的?
  2. 如何定义自己的装饰器?

1 个答案:

答案 0 :(得分:21)

事实上,你应该调用“注释”装饰器,因为它略有不同;-)它们允许装饰物体。这篇博文可以在这里提供更多提示:http://blog.thoughtram.io/angular/2015/05/03/the-difference-between-annotations-and-decorators.html

因此装饰器不是Angular特有的。有一个针对ES7的提议,它们也受到TypeScript语言本身的支持。这可以与reflect-metadata库(它包含在angular2-polyfills.js文件中)结合使用,以设置和获取元素的元数据。

  • 类装饰器

    export function MyClassDecorator(value: string) {
      return function (target: Function) {
        Reflect.defineMetadata("MyClassDecorator", value, target);
      }
    }
    
    @Component({ ... })
    @MyClassDecorator("my metadata")
    export class AppComponent {
      constructor() {
        let decoratorValue: string
          = Reflect.getMetadata("MyClassDecorator", this.constructor);
      }
    }
    
  • 功能装饰器

    export function log(target: Object,
                    propertyKey: string,
                    descriptor: TypedPropertyDescriptor<any>) {
      var originalMethod = descriptor.value;
    
      descriptor.value = function(...args: any[]) {
        console.log("The method args are: " + JSON.stringify(args));
        var result = originalMethod.apply(this, args);
        console.log("The return value is: " + result);
        return result;
      };
    
      return descriptor;
    }
    
    export class AppComponent {
      constructor() { }
    
      @MyMethodDecorator
      getMessage() {
        return 'test';
      }
    }
    
  • 参数装饰器

    export function MyParameterDecorator(param1) {
      return function(target: any, methodKey: string | symbol,
                      parameterIndex: number) {
        (...)
      };
    }
    
  • 类属性装饰器

    export function MyPropertyDecorator(target: any,
            propertyKey: string | symbol) {
      (...)
    }
    

因此,通常装饰器对应于一个函数。如果不使用参数,则无需返回包装。如果你想使用装饰器的参数,你需要一个额外的函数来获取参数并返回实际装饰器:

// In the case of a parameter decorator
// myMethod(@MyDecoratorWithoutParameter someParam) { ... }
export function MyDecoratorWithoutParameter(target: any,
    propertyKey: string | symbol, parameterIndex: number) {
  console.log('decorator called');
}

// myMethod(@MyDecoratorWithParameter('test') someParam) { ... }
export function MyDecoratorWithParameter(param1) {
  // param1 contains 'test'
  return function(target: any, propertyKey: string | symbol,
                  parameterIndex: number) {
    console.log('decorator called');
  };
}

这是一个与我的样本对应的plunkr:https://plnkr.co/edit/0VBthTEuIAsHJjn1WaAX?p=preview

以下链接可以为您提供有关TypeScript的更多详细信息:

希望它可以帮到你, 亨利