Angular组件有装饰器:
@Component({ ... })
export class MyAngularComponent {
@Input() myInputParam: MyType;
@Input() myOtherInputParam: MyOtherType;
@Output() myOutputParam: MyOtherOutputType;
}
我有一个Angular库,如果我可以在给定的组件类中以编程方式检索Angular的@Input()
装饰器,那么可以避免大量的代码重复(并减少bundle大小)(虽然属于图书馆)。
但我怀疑这种实现的可移植性。我已经读过某个地方,如果Angular应用程序是在启用了AoT的情况下构建的(并且只使用了Angular装饰器),则不需要Reflect polyfill(在运行时读取装饰器所需)。所以我认为我不能只使用Reflect.*
。 Angular如何存储装饰器?是否有一种可靠的,面向未来的阅读方式?
缩小不应该是一个问题,因为它只会用于读取库组件的装饰器,所以我可以控制它。
所以,如果这种方法可以通过便携方式进行(或者不是,我仍然感兴趣),我该如何阅读这些装饰者?
答案 0 :(得分:8)
我在某处读过Reflect polyfill(需要阅读 如果构建了Angular应用程序,则不需要运行时的装饰器 启用AoT ...... Angular如何存储装饰器?
事实上,Angular计划删除对Reflect
对象的依赖,即使在运行时中也是如此。因此,在最新的v5中,Reflect.defineMetadata
已替换为负责将元数据附加到类的Object.defineProperty
中的makeDecorator
。以下是相关代码:
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;
};
这意味着在v5中,您可以访问组件类上的装饰器,如下所示:
export class AppComponent {
constructor() {
console.log((<any>AppComponent).__annotations__);
}
是否有可靠,面向未来的方式来阅读它们? 我不认为Angular有任何面向未来的事情。
使用AOT编译应用程序时 Angular使用静态代码分析,并且在很大程度上依赖于TS编译器生成的AST。如果您有兴趣在构建时访问装饰器,我想这是可行的方法,我称之为最具前瞻性的解决方案。