为啥 Angular 要求我们在声明数组和 entryComponents 数组中声明动态组件?

Posted

技术标签:

【中文标题】为啥 Angular 要求我们在声明数组和 entryComponents 数组中声明动态组件?【英文标题】:Why Angular requires us to declare dynamic components in declarations array and entryComponents array?为什么 Angular 要求我们在声明数组和 entryComponents 数组中声明动态组件? 【发布时间】:2019-03-19 11:25:50 【问题描述】:

我正在为我的一个项目实施动态组件。动态组件的概念是一旦需要它们就会进入内存,并且在任何模板中都没有引用。

根据官方docs的说法,我们在entryComponents中声明了这些组件,以防止它们在摇树过程中被丢弃,因为它们没有模板引用。

下面是app.module.ts,我在entryComponents数组中声明了我的两个动态组件SlideOneComponentSlideTwoComponent

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

上面app.module.ts我收到以下错误:

只要将两个动态组件都添加到declarations 数组,上述错误就会消失。上述官方文档还说,我们不需要声明可从entryComponentsbootstrap 组件访问的组件。我也访问了this 答案,但这似乎不够令人满意,因为它是关于 Ionic 的。

请帮助我知道我在这方面缺少什么。提前致谢! :)

【问题讨论】:

The aforementioned official docs also says that we do not need to declare components that are reachable from entryComponents or bootstrap component. 你能指出文档说明这一点的确切位置吗? 您必须在declarations 数组中声明任何组件。除此之外,入口组件还必须在entryComponents 数组(NgModule 或组件级别)中显式或通过bootstrap 数组或路由声明 【参考方案1】:

从这句话中可以看出(在阅读字里行间):

虽然 @NgModule 装饰器有一个 entryComponents 数组,但大多数 您不必显式设置任何条目组件的时间,因为 Angular 添加了 @NgModule.bootstrap 中列出的组件以及 自动路由定义到入口组件。

您将常用组件添加到 EntryComponents 数组中隐式,这意味着它们被添加到两个数组中 - Declarations 和 EntryComponents(而您只在 Declarations 数组中添加了它)。因此,您还必须将动态组件显式添加到两个数组中。

声明 目的是使指令(组件等)可用于模块中的其他类,并将其选择器与 html 匹配。

EntryComponents 告诉 Angular 创建一个 componentFactory,它是由编译器根据您在 @Component 装饰器中提供的元数据创建的,因此您以后可以在 createComponent() 中使用它。

正如所见,这两个数组的用途非常不同,并且两者都是创建组件所必需的。如果组件不是动态创建的,编译器会读取它的元数据并创建一个componentFactory,但是编译器不知道动态组件,所以你必须在它运行之前通知它动态组件,因为他只运行一次 - 在编译时:)

【讨论】:

但这很矛盾,因为根据文档,entryComponents 中声明的组件是可访问的,不需要声明。另一种方法是在声明数组中声明它,但如果无法从模板中引用的组件或通过 entryComponents 中的组件访问它,我们仍然需要在 entryComponents 中声明它。所以无论是什么情况,我都必须在两个数组中声明。我说对了吗?但是我的上述假设仍然不能清除理解。 也许您误读了某些内容,或者我没有看到文档声明它“不需要声明”。我用更多细节编辑了我的答案 根据文档:。 “对于生产应用程序,您希望加载尽可能少的代码。代码应仅包含您实际需要的类,并排除从未使用过的组件。因此,Angular 编译器仅生成可从 entryComponents 访问的组件的代码; 这意味着添加更多对@NgModule.declarations 的引用并不意味着它们一定会包含在最终包中。”。所以根据这个,即使我们只在 entryComponents 中添加动态组件,Angular 编译器也应该能够找到它,对吗? 同意,但是由于它不在声明数组中,它的选择器不会与html匹配,其他类将无法访问它。你的错误来自这里 -github.com/angular/angular/blob/master/packages/compiler/src/…。如您所见,它需要对 NgModel 的引用,因此编译器会找到您的组件但无法确定它属于哪里

以上是关于为啥 Angular 要求我们在声明数组和 entryComponents 数组中声明动态组件?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 C 中为数组声明和指向数组声明的指针动态分配的内存不同? [复制]

为啥 Angular 2 ngOnChanges 不响应输入数组推送

为啥 SoapClient 在文档/文字样式中使用 WSDL 返回带有额外关键元素的数组?

Angular - 为啥我得到对象而不是对象数组?

为啥 malloc() 和普通数组声明分配的堆栈帧大小不同?

为啥我无法完成数组类型的 typedef 名称?