简体   繁体   English

如何在Angular中检索组件的元数据

[英]How to retrieve a component's metadata in Angular

An Angular component has decorators: Angular组件有装饰器:

@Component({ ... })
export class MyAngularComponent {
  @Input() myInputParam: MyType;
  @Input() myOtherInputParam: MyOtherType;
  @Output() myOutputParam: MyOtherOutputType;
}

I've got an Angular library where a lot of code repetitions could be avoided (and bundle size reduced) if I could programmatically retrieve Angular's @Input() decorators inside a given component class (that belongs to the library, though) . 我有一个Angular库,如果我能以编程方式检索给定组件类(属于库 @Input() Angular的@Input()装饰器,那么可以避免大量代码重复(并减少bundle大小

But I have doubts on the portability of such an implementation. 但我怀疑这种实现的可移植性。 I've read somewhere that the Reflect polyfill (needed to read decorators at runtime) isn't needed if the Angular app has been built with AoT enabled (and given that only Angular decorators are used). 我已经读过某个地方,如果Angular应用程序是在启用了AoT的情况下构建的(并且只使用了Angular装饰器),则不需要Reflect polyfill(在运行时读取装饰器所需)。 So I presume I can't just use Reflect.* . 所以我认为我不能只使用Reflect.* How does Angular stores the decorators? Angular如何存储装饰器? Is there a reliable, future-proof way to read them? 是否有可靠,面向未来的方式来阅读它们?

Minification shouldn't be a problem since that would be used to read decorators of library's components only, so I have control on this. 缩小应该不是问题,因为它只用于读取库组件的装饰器,所以我可以控制它。

So, if that's doable in a portable way (or not, I'm still interested otherwise), how can I read those decorators? 所以,如果这是可行的方式(或者不是,我仍然感兴趣),我怎么能读取那些装饰器?

I've read somewhere that the Reflect polyfill (needed to read decorators at runtime) isn't needed if the Angular app has been built with AoT enabled... How does Angular stores the decorators? 我已经读过某个地方,如果在启用AoT的情况下构建了Angular应用程序,则不需要Reflect polyfill(在运行时读取装饰器)... Angular如何存储装饰器?

In fact, Angular plans to remove dependency on the Reflect object even in runtime . 实际上,Angular计划在运行时删除对Reflect对象的依赖。 For that reason, in the newest v5 the Reflect.defineMetadata has been replaced with Object.defineProperty in the makeDecorator that is responsible for attaching the metadata to the class. 因此,在最新的v5中, Reflect.defineMetadata已替换为Object.defineProperty中的makeDecorator ,后者负责将元数据附加到类。 Here is the relevant code: 这是相关代码:

export const ANNOTATIONS = '__annotations__';
export function makeDecorator(
    ...
    const TypeDecorator: TypeDecorator = <TypeDecorator>function TypeDecorator(cls: Type<any>) {
      // Use of Object.defineProperty is important since it creates non-enumerable property which
      // prevents the property is copied during subclassing.
      const annotations = cls.hasOwnProperty(ANNOTATIONS) ?
          (cls as any)[ANNOTATIONS] :
          Object.defineProperty(cls, ANNOTATIONS, {value: []})[ANNOTATIONS]; <-----
      annotations.push(annotationInstance);
      return cls;
    };

It means that in the v5 you can access decorators on the component class like this: 这意味着在v5中你可以访问组件类上的装饰器,如下所示:

export class AppComponent {
    constructor() {
        console.log((<any>AppComponent).__annotations__);
    }

Is there a reliable, future-proof way to read them? 是否有可靠,面向未来的方式来阅读它们? I don't think there's anything future-proof with Angular. 我不认为Angular有任何未来的证据。

When compiling an application using AOT Angular uses static code analysis and heavily relies on the AST produced by the TS compiler. 使用AOT Angular编译应用程序时, 使用静态代码分析并严重依赖TS编译器生成的AST。 If you're interested in accessing decorators in the build time I guess that is the way to go and I would call it the most future-proof solution. 如果你有兴趣在构建时访问装饰器,我想这是要走的路,我称之为最具前瞻性的解决方案。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM