Почему Angular требует, чтобы мы объявляли динамические компоненты в массиве объявлений и массиве entryComponents?

Я реализовывал динамические компоненты для одного из моих проектов. Концепция динамических компонентов заключается в том, что они попадают в память по мере необходимости и не имеют ссылок ни в одном шаблоне.

Согласно официальной документации, мы объявляем такие компоненты в entryComponents, чтобы предотвратить их отбрасывание в сотрясение дерева, так как у них нет ссылки на шаблон.

Ниже приведен app.module.ts, где я объявил два своих динамических компонента SlideOneComponent и SlideTwoComponent в массиве entryComponents:

  @NgModule({
  declarations: [
    AppComponent,
    ButtonComponent,
    AdDirective
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  entryComponents: [
      SlideOneComponent,
      SlideTwoComponent,
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

С выше app.module.ts я получаю следующую ошибку:

введите описание изображения здесь

Вышеупомянутая ошибка исчезает, как только я добавляю оба своих динамических компонента в массив declarations. В вышеупомянутых официальных документах также говорится, что нам не нужно объявлять компоненты, доступные из компонента entryComponents или bootstrap. Я также посетил этот ответ, но это кажется недостаточно удовлетворительным, поскольку это относится к Ionic.

Пожалуйста, помогите мне узнать, где мне не хватает этого. Заранее спасибо! :)


person patrick.1729    schedule 15.10.2018    source источник
comment
The aforementioned official docs also says that we do not need to declare components that are reachable from entryComponents or bootstrap component. Можете ли вы указать точное место, где это указано в документе?   -  person yurzui    schedule 16.10.2018
comment
Вы должны объявить любой компонент в массиве declarations. В дополнение к этому, входные компоненты также должны быть объявлены в массиве entryComponents (уровень NgModule или Component) либо явно, либо через массив bootstrap, либо в виде маршрута.   -  person yurzui    schedule 16.10.2018


Ответы (1)


Как видно из этой цитаты (при чтении между строк):

Хотя декоратор @NgModule имеет массив entryComponents, в большинстве случаев вам не нужно будет явно задавать какие-либо компоненты входа, потому что Angular автоматически добавляет компоненты, перечисленные в @NgModule.bootstrap, и те, что в определениях маршрута, к компонентам входа.

Обычные компоненты вы добавляете в массив EntryComponents неявно, то есть они добавляются в оба массива - Declarations и EntryComponents (пока вы добавляли только в массив Declarations). Таким образом, вы должны добавить динамические компоненты явно в оба массива.

Объявления предназначены для того, чтобы сделать директиву (компонент и т. д.) доступной для других классов в вашем модуле и сопоставить ее селектор с HTML.

EntryComponents указывает Angular создать componentFactory, который создается компилятором из метаданных, предоставленных вами в декораторе @Component, чтобы впоследствии вы могли использовать его в createComponent().

Как видно, эти два массива служат совершенно разным целям, и оба необходимы для создания компонента. Если компонент создается не динамически, компилятор читает его метаданные и создает componentFactory, но компилятор не знает о динамических компонентах, поэтому вы должны сообщить ему о динамических компонентах до его запуска, так как он запускается только один раз - во время компиляции :)

person Julius    schedule 15.10.2018
comment
Но это довольно противоречиво, поскольку согласно документам компоненты, объявленные в entryComponents, доступны и их не нужно объявлять. Другой способ — объявить его в массиве объявлений, но все же нам нужно объявить его в entryComponents, если он недоступен из компонентов, на которые есть ссылки в шаблоне, или через компоненты в entryComponents. Поэтому в любом случае я должен объявить в обоих массивах. Я правильно понимаю? Но все же мое вышеприведенное предположение не проясняет понимания. - person patrick.1729; 15.10.2018
comment
Может быть, вы что-то неправильно прочитали, или я не видел, чтобы в документах говорилось, что это не нужно объявлять. Я отредактировал свой ответ с более подробной информацией - person Julius; 15.10.2018
comment
Согласно документам:. Для производственных приложений вы хотите загрузить как можно меньше кода. Код должен содержать только те классы, которые вам действительно нужны, и исключать компоненты, которые никогда не используются. По этой причине компилятор Angular генерирует код только для тех компонентов, которые доступны из entryComponents; Это означает, что добавление большего количества ссылок на @NgModule.declarations не означает, что они обязательно будут включены в окончательный пакет. Таким образом, согласно этому, даже если мы добавим динамические компоненты только к entryComponents, компилятор Angular должен быть в состоянии найти это, это правильно? - person patrick.1729; 16.10.2018
comment
Согласен, но поскольку его нет в массиве объявлений, его селектор не будет сопоставляться с html, и другие классы не смогут получить к нему доступ. Ваша ошибка исходит отсюда - github. com/angular/angular/blob/master/packages/compiler/src/. Как видите, ему нужна ссылка на NgModel, поэтому компилятор находит ваш компонент, но не может понять, где он находится - person Julius; 16.10.2018