Как получить метаданные компонента в Angular

Угловой компонент имеет декораторы:

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

У меня есть библиотека Angular, в которой можно было бы избежать много повторений кода (и уменьшить размер пакета), если бы я мог программно получить Angular @Input() декораторы внутри заданного класса компонента (хотя он и принадлежит библиотеке).

Но я сомневаюсь в переносимости такой реализации. Я где-то читал, что полифилл Reflect (необходимый для чтения декораторов во время выполнения) не нужен, если приложение Angular было создано с включенным AoT (и учитывая, что используются только Angular декораторы). Итак, я полагаю, я не могу просто использовать Reflect.*, Как Angular хранит декораторы? Есть ли надежный, ориентированный на будущее способ их прочтения?

Минимизация не должна быть проблемой, так как она будет использоваться для чтения декораторов только компонентов библиотеки, так что у меня есть контроль над этим.

Итак, если это выполнимо переносимым способом (или нет, я все еще заинтересован в ином), как я могу читать эти декораторы?

1 ответ

Решение

Я где-то читал, что полифилл Reflect (необходимый для чтения декораторов во время выполнения) не нужен, если приложение 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 использует статический анализ кода и в значительной степени опирается на AST, создаваемый компилятором TS. Если вы заинтересованы в доступе к декораторам во время сборки, я думаю, что это правильный путь, и я бы назвал его наиболее перспективным решением.

Другие вопросы по тегам