简体   繁体   English

装饰器何时以及如何应用于@angular包中的装饰类

[英]When and how s decorator applied to the decorated classes from the @angular packages

If I use a decorator in my class the decorator is evaluated when importing the class. 如果我在课堂上使用装饰器,则在导入类时会评估装饰器。 Here is the small example: 这是一个小例子:

@NgModule({ ... })
export class BModule { ... }

Transpiled as: 译为:

var BModule = (function () {
    function BModule() {
    }
    BModule = __decorate([  <---------- decorators are applied here
        core_1.NgModule({...})
    ], BModule);
    return BModule;
}());
exports.BModule = BModule;

However, when the module or any other decorator is applied in the @angular bundles the output is the following: 但是,当模块或任何其他装饰器应用于@angular捆绑包时,输出如下:

var HttpClientModule = (function () {
    function HttpClientModule() {
    }
    return HttpClientModule;
}());
HttpClientModule.decorators = [
    { type: _angular_core.NgModule, args: [{ ... },] },
];

As you can see, the decorators are not applied here. 如您所见,装饰器未在此处应用。 They are just saved in the decorators property. 它们只是保存在decorators属性中。 Why is it different from my code? 为什么它与我的代码不同?

The reason I'm asking is that when importing my decorated classes I expect it to have decorators applied and so using Reflect is possible: 我问的原因是,导入装饰类时,我希望它应用装饰器,因此可以使用Reflect

const providers = Reflect.getOwnMetadata('annotations', BModule);

However, it doesn't work this way with decorated classes from the @angular packages. 但是,它不适用于@angular包中的修饰类。

When angulat resolves annotations it has three options : 当angulat解析注释时,它具有三个选项

1) Direct API 1)直接API

// Prefer the direct API.
if ((<any>typeOrFunc).annotations && (<any>typeOrFunc).annotations !== parentCtor.annotations) {
  let annotations = (<any>typeOrFunc).annotations;
  if (typeof annotations === 'function' && annotations.annotations) {
    annotations = annotations.annotations;
  }
  return annotations;
}

We usually use this API when write code in ES5 在ES5中编写代码时,我们通常会使用此API

MyComponent.annotations = [
  new ng.Component({...})
]

2) API of tsickle 2)滴答API

// API of tsickle for lowering decorators to properties on the class.
if ((<any>typeOrFunc).decorators && (<any>typeOrFunc).decorators !== parentCtor.decorators) {
  return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators);
}

This way angular reads annotations from @angular/(core|material...) libraries. 这样,angular从@angular/(core|material...)库中读取注释。 Angular compiles libraries this way because it helps to optimize bundle. Angular以这种方式编译库,因为它有助于优化包。 For example we do not need to ship decorator helpers like _decorate, __metadata and the code will be executed faster. 例如,我们不需要_decorate, __metadata类的装饰器助手_decorate, __metadata并且代码执行速度更快。

For that angular uses tslib when building library by running tsc with --importHelpers options https://github.com/angular/angular/blob/master/build.sh#L127 . 为此,在通过--importHelpers选项https://github.com/angular/angular/blob/master/build.sh#L127运行tsc构建库时,angular使用tslib

Angular material does the same thing https://github.com/angular/material2/blob/master/tools/package-tools/rollup-helpers.ts#L9-L11 角材料做同样的事情https://github.com/angular/material2/blob/master/tools/package-tools/rollup-helpers.ts#L9-L11

// Import tslib rather than having TypeScript output its helpers multiple times.
// See https://github.com/Microsoft/tslib
'tslib': 'tslib',

3) Using Reflect 3)使用反射

// API for metadata created by invoking the decorators.
if (this._reflect && this._reflect.getOwnMetadata) {
  return this._reflect.getOwnMetadata('annotations', typeOrFunc);
}

This API is used when we use metadata emitted by typescript 当我们使用由Typescript发出的元数据时,将使用此API

To ensure you will get metadata correctly you can consider using function like: 为了确保正确获取元数据,可以考虑使用类似以下的功能:

declare let Reflect: any;
function getAnnotations(typeOrFunc: Type<any>): any[]|null {
  // Prefer the direct API.
  if ((<any>typeOrFunc).annotations) {
    let annotations = (<any>typeOrFunc).annotations;
    if (typeof annotations === 'function' && annotations.annotations) {
      annotations = annotations.annotations;
    }
    return annotations;
  }

  // API of tsickle for lowering decorators to properties on the class.
  if ((<any>typeOrFunc).decorators) {
    return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators);
  }

  // API for metadata created by invoking the decorators.
  if (Reflect && Reflect.getOwnMetadata) {
    return Reflect.getOwnMetadata('annotations', typeOrFunc);
  }
  return null;
}

function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[] {
  if (!decoratorInvocations) {
    return [];
  }
  return decoratorInvocations.map(decoratorInvocation => {
    const decoratorType = decoratorInvocation.type;
    const annotationCls = decoratorType.annotationCls;
    const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];
    return new annotationCls(...annotationArgs);
  });
}


const annotations = getAnnotations(AppModule);

Update: 更新:

API for metadata created by invoking the decorators was changed in 5.0.0-beta.4 在5.0.0-beta.4中更改了通过调用装饰器创建的元数据API

const ANNOTATIONS = '__annotations__';

// API for metadata created by invoking the decorators.

if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) {
   return (typeOrFunc as any)[ANNOTATIONS];
}
return null;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 装饰器如何在多个类的情况下应用于角度类 - How's decorator applied to classes in angular in case of multiple classes 如何在不出错的情况下实现 OnInit:Class 正在使用 Angular 功能但未进行装饰。 请添加显式 Angular 装饰器 - How do I implement OnInit without getting error: Class is using Angular features but is not decorated. Please add an explicit Angular decorator 如何在接口中定义angular的@Input装饰器? - How to define angular's @Input decorator in an interface? angular 的 @Attribute 装饰器是如何工作的? - How angular's @Attribute decorator works? Angular, 如何在从服务器获取数据并应用 *ngFor 后通过 Jquery 获取类? - Angular, How to get classes by Jquery after getting data from server and *ngFor has been applied for them? Angular:如何从自定义装饰器获取ElementRef - Angular: How to get ElementRef From Custom Decorator 问:Angular 组件损坏 - “类正在使用 Angular 功能但未装饰。请添加显式 Angular 装饰器” - Q: Angular components broken - "Class is using Angular features but is not decorated. Please add an explicit Angular decorator" Angular 15: Class 正在使用 Angular 功能但未修饰。 请添加明确的 Angular 装饰器。(-992007) - Angular 15 : Class is using Angular features but is not decorated. Please add an explicit Angular decorator.(-992007) 如何在Angular 2组件上通过HTML应用类? - How can I get the classes applied via HTML on an Angular 2 component? 类使用 Angular 特性但没有修饰。 请添加一个显式的 Angular 装饰器 - Class is using Angular features but is not decorated. Please add an explicit Angular decorator
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM