【问题标题】:How are decorators (annotations) compiled in Typescript?Typescript 中如何编译装饰器(注解)?
【发布时间】:2016-04-27 13:32:15
【问题描述】:

在 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. 如何定义自己的装饰器?

【问题讨论】:

标签: typescript angular


【解决方案1】:

事实上,您应该调用“注解”装饰器,因为它略有不同;-) 它们允许装饰对象。这篇博文可以在这里提供更多提示: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 的更多详细信息:

希望对你有帮助 蒂埃里

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-11
    • 2019-11-12
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 2019-01-07
    • 2019-05-07
    相关资源
    最近更新 更多