装饰器何时何地应用于@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 { ... }
翻译为:
var BModule = (function () {
function BModule() {
}
BModule = __decorate([ <---------- decorators are applied here
core_1.NgModule({...})
], BModule);
return BModule;
}());
exports.BModule = BModule;
但是,当在@angular
捆绑包中应用模块或任何其他装饰器时,输出如下:
However, when the module or any other decorator is applied in the @angular
bundles the output is the following:
var HttpClientModule = (function () {
function HttpClientModule() {
}
return HttpClientModule;
}());
HttpClientModule.decorators = [
{ type: _angular_core.NgModule, args: [{ ... },] },
];
如您所见,装饰器未在此处应用.它们只是保存在decorators
属性中.为什么它与我的代码不同?
As you can see, the decorators are not applied here. They are just saved in the decorators
property. Why is it different from my code?
我问的原因是,在导入装饰类时,我希望它应用装饰器,因此可以使用Reflect
:
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:
const providers = Reflect.getOwnMetadata('annotations', BModule);
但是,它不适用于@angular
包中的修饰类.
However, it doesn't work this way with decorated classes from the @angular
packages.
推荐答案
When angulat resolves annotations it has three options:
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;
}
在ES5中编写代码时,我们通常使用此API
We usually use this API when write code in ES5
MyComponent.annotations = [
new ng.Component({...})
]
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);
}
这种方式,angular从@angular/(core|material...)
库中读取注释. Angular以这种方式编译库,因为它有助于优化包.例如,我们不需要运送_decorate, __metadata
之类的装饰器助手,代码将更快地执行.
This way angular reads annotations from @angular/(core|material...)
libraries. Angular compiles libraries this way because it helps to optimize bundle. For example we do not need to ship decorator helpers like _decorate, __metadata
and the code will be executed faster.
为此,在使用--importHelpers
选项运行tsc构建库时,angular使用tslib
https://github.com/angular/angular/blob/master/build.sh#L127 .
For that angular uses tslib
when building library by running tsc with --importHelpers
options https://github.com/angular/angular/blob/master/build.sh#L127.
角材料做同样的事情 3)使用反射
// API for metadata created by invoking the decorators.
if (this._reflect && this._reflect.getOwnMetadata) {
return this._reflect.getOwnMetadata('annotations', typeOrFunc);
}
当我们使用由打字稿发出的元数据时,将使用此API
This API is used when we use metadata emitted by typescript
为确保正确获取元数据,您可以考虑使用以下函数:
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);
更新:
在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;
这篇关于装饰器何时何地应用于@angular包中的装饰类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!