角 ngModule 中的 entry 是什么?

我工作的 Ionic应用程序(2.0.0-rc0) ,这取决于 angular 2。因此,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中定义。那么有什么必要重复它们呢?如果这里没有包含组件会发生什么?

104012 次浏览

注意: 不推荐使用角度9.0.0中的 EntryComponent 请参阅 有棱角的医生表单的更多细节。

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

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

脱机模板编译器(OTC)只生成实际使用的组件。如果组件不直接用在模板中,OTC 就无法知道它们是否需要编译。通过 entryComponent,您可以告诉 OTC 也编译这些组件,以便它们在运行时可用。

什么是条目组件? (angular.io)

NgModule 文档(angular.io)

定义定义此组件时也应编译的组件。对于这里列出的每个组件,Angular 将创建一个 Component entFactory 并将其存储在 Component entFactoryResolver 中。

如果你不列出一个动态添加的组件到 entryComponents,你会得到一个错误消息一回合缺少一个工厂,因为 Angular 不会创建一个。

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

你不会得到比有角度的文档更好的解释: 入口组件Ngmodule-FAQ

下面是角度博士的解释。

一个入口组件是任何组件,角加载强制类型。

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

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

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

引导的根 AppComponent是一个入口组件。则其选择器匹配 index.html 中的元素标记。但是 index.html不是组件模板,而且 AppComponent选择器不匹配任何组件模板中的元素。

角度动态加载 AppComponent,因为它要么在 @NgModule.bootstrap中按类型列出,要么使用模块的 ngDoBootstrap 方法强制引导。

路由定义中的组件也是条目组件。路由定义按照组件的类型引用组件。路由器忽略路由组件的选择器(如果它有的话) ,并将组件动态加载到 RouterOutlet中。

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

Angular 自动将下列类型的组件添加到模块的 entryComponents中:

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

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

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

  • 如果在 Html中没有使用组件,例如: <my-component />,那么就需要使用它
  • 例如,使用角度材质对话框时,你使用它们 间接地,它们是在 TS 码内部创建的,而不是 html:
openDialog() {
const dialogRef = this.dialog.open(MyExampleDialog, { width: '250px'});
}

这需要您将其注册为 entry 组件:

  • entryComponents: [MyExampleDialog]

否则你会得到一个错误:

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

Entry 组件数组仅用于定义在 html 中没有找到并且动态创建的组件。Angular 需要这个提示来查找条目组件并编译它们。

有两种主要类型的进入组成部分:

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

有关条目组件的详细信息,请参阅 angular.io Https://angular.io/guide/entry-components

关于 entryComponent的一点背景知识

entryComponent是任何组件的角度负载必须。你可以通过在 NgModule或路由定义中引导它来声明 entryComponent

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

文档 说明如下

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

现在回答你关于 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);

由于 Ivy 允许这个特性被废弃,因此可以从模块声明中删除,因此不再需要 Angular 9 entryComponents

已废弃的 API 和特性-不再需要 entryComponentsANALYZE_FOR_ENTRY_COMPONENTS

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

Angular Ivy

Ivy 是 Angular 下一代编译和渲染管道的代号。在 Angular 的版本9中,默认情况下使用新的编译器和运行时指令,而不是旧的编译器和运行时(称为视图引擎)。