【问题标题】:What is entryComponents in angular ngModule?Angular ngModule 中的 entryComponents 是什么?
【发布时间】:2017-02-06 22:43:07
【问题描述】:

我正在开发一个依赖于angular 2Ionic 应用程序(2.0.0-rc0)。所以新引入了ngModules。我在下面添加我的app.module.ts.

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { Users } from '../pages/users/users';

@NgModule({
  declarations: [
    MyApp,
    Users
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    Users
  ]
})
export class AppModule {}

entryComponents 在这里做什么? Components 已在 declarations 中定义。那么重复它们有什么必要呢?如果我不在这里包含组件会怎样?

【问题讨论】:

  • Angular 使用 entryComponents 来启用“摇树”,即只编译项目中实际使用的组件,而不是编译 ngModule 中的所有 declared 但从未使用过的组件。 angular.io/docs/ts/latest/cookbook/…入口组件-

标签: angular angular-components angular-module


【解决方案1】:

这适用于使用ViewContainerRef.createComponent() 添加的动态添加的组件。将它们添加到entryComponents 告诉离线模板编译器编译它们并为它们创建工厂。

路由配置中注册的组件也会自动添加到entryComponents,因为router-outlet 也使用ViewContainerRef.createComponent() 将路由组件添加到DOM。

离线模板编译器 (OTC) 仅构建实际使用的组件。如果组件没有直接在模板中使用,OTC 就无法知道它们是否需要编译。使用 entryComponents,您可以告诉 OTC 也编译这些组件,以便它们在运行时可用。

What is an entry component? (angular.io)

NgModule docs (angular.io)

定义该组件时也应编译的组件。对于这里列出的每个组件,Angular 都会创建一个 ComponentFactory 并将其存储在 ComponentFactoryResolver 中。

如果您没有将动态添加的组件列出到 entryComponents,您将收到一条关于缺少工厂的错误消息,因为 Angular 不会创建工厂。

另见https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html

【讨论】:

  • 坦率地说,我知道它的 100% 正确答案,但为我做了保镖,你能详细说明一下吗?
  • 很难说出不清楚的地方。离线模板编译器 (OTC) 仅构建实际使用的组件。如果组件没有直接在模板中使用,OTC 就无法知道它们是否需要编译。使用entryComponents,您可以告诉 OTC 也编译这些组件,以便它们在运行时可用。
  • stackoverflow.com/questions/36325212/… 就是这样一个例子
  • 所以一般来说,如果组件列在declarations,它也应该列在entryComponents,对吧?
  • 仅当在您的代码中使用createComponent 动态添加组件时,或者例如也使用thod API 添加组件的路由器。
【解决方案2】:

其他答案提到了这一点,但基本总结是:

  • html 中未使用组件时需要它,例如:<my-component />
  • 例如,对于 Angular Material Dialogs,您间接使用它们,它们是在 TS 代码而不是 html 中创建的:
openDialog() {
    const dialogRef = this.dialog.open(MyExampleDialog, { width: '250px'});
}

这需要您将其注册为 entryComponent:

  • entryComponents: [MyExampleDialog]

否则会报错:

  • ERROR Error: No component factory found for MyExampleDialog. Did you add it to @NgModule.entryComponents?

【讨论】:

  • 这里最好的解释。
  • 简单,谢谢。 XD
【解决方案3】:

你不会得到比 Angular 文档更好的解释:entry-componentsngmodule-faq

以下是角度文档的解释。

入口组件是 Angular 按类型强制加载的任何组件。

通过其选择器以声明方式加载的组件不是入口组件。

大多数应用程序组件都是以声明方式加载的。 Angular 使用组件的选择器来定位模板中的元素。然后它创建组件的 HTML 表示并将其插入到 DOM 中的选定元素处。这些不是入口组件。

少数组件只是动态加载,从不在组件模板中引用。

引导的根AppComponent 是一个入口组件。没错,它的选择器匹配 index.html 中的元素标签。但index.html 不是组件模板,AppComponent 选择器不匹配任何组件模板中的元素。

Angular 动态加载 AppComponent,因为它要么在 @NgModule.bootstrap 中按类型列出,要么使用模块的 ngDoBootstrap 方法强制地进行增强。

路由定义中的组件也是入口组件。路由定义通过其类型引用组件。路由器会忽略路由组件的选择器(如果它甚至有选择器)并将组件动态加载到RouterOutlet

编译器无法通过在其他组件模板中查找这些入口组件来发现它们。您必须通过将它们添加到 entryComponents 列表来告诉它。

Angular 会自动将以下类型的组件添加到模块的entryComponents

  • @NgModule.bootstrap 列表中的组件。
  • 路由器配置中引用的组件。

您不必明确提及这些组件,尽管这样做是无害的。

【讨论】:

  • 现在 Angular 文档不可用,所以非常感谢!
  • 这似乎没有提到路由配置中的组件会自动添加到 entryComponents 中(因此您通常永远不需要定义它)。
  • 如果我们创建一个组件用作EntryComponent,我们应该删除selector 属性吗? (因为它不会被使用)
  • 新手最佳答案
【解决方案4】:

从 Angular 9 开始,由于 Ivy 允许弃用此功能,因此不再需要 entryComponents,因此可以从模块声明中删除。

Deprecated APIs and features - entryComponents and ANALYZE_FOR_ENTRY_COMPONENTS no longer required

以前,NgModule 定义中的entryComponents 数组用于告诉编译器将动态创建和插入哪些组件。使用 Ivy,这不再是必需的,entryComponents 数组可以从现有的模块声明中删除。这同样适用于ANALYZE_FOR_ENTRY_COMPONENTS 注入令牌。

Angular Ivy

Ivy 是 Angular 的下一代编译和渲染管道的代号。在 Angular 9 版本中,默认使用新的编译器和运行时指令,而不是旧的编译器和运行时指令,即 View Engine。

【讨论】:

  • 没有回答这个问题,但它仍然是一个信息丰富的答案。 +1。
【解决方案5】:

entryComponents 数组仅用于定义在 html 中找不到并动态创建的组件。 Angular 需要这个提示来查找入口组件并编译它们。

入口组件主要有两种:

  • 引导的根组件。
  • 您在路由定义中指定的组件。

有关入口组件的更多详细信息,请参阅 angular.io https://angular.io/guide/entry-components

【讨论】:

    【解决方案6】:

    关于entryComponent的一些背景知识

    entryComponent 是 Angular 强制加载的任何组件。您可以通过在NgModule 或路由定义中引导它来声明entryComponent

    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        FormsModule,
        HttpClientModule,
        AppRoutingModule
      ],
      providers: [],
      bootstrap: [AppComponent] // bootstrapped entry component
    })
    

    Documentation 在下面说

    为了对比这两种类型的组件,有一些组件 包含在模板中,它们是声明性的。此外, 您必须加载一些组件;也就是进入 组件。

    现在回答您关于entryComponents 的具体问题

    @NgModule 文件中有 entryComponents 数组。如果组件是使用ViewContainerRef.createComponent() 引导的,您可以使用它来添加entryComponents

    也就是说,您是在动态创建组件,而不是通过引导或在模板中创建。

    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(myComp.component);
    const viewContainerRef = this.compHost.viewContainerRef;
    viewContainerRef.clear();
    const componentRef = viewContainerRef.createComponent(componentFactory);
    

    【讨论】:

      【解决方案7】:
      猜你喜欢
      • 2017-03-16
      • 2017-05-03
      • 2017-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      • 1970-01-01
      相关资源
      最近更新 更多