我正在开发一个依赖于 angular 2
的 Ionic
应用程序 ( 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
中定义。那么重复它们有什么必要呢?如果我在这里不包含组件会发生什么?
ngModule
中的 declared
但从未使用过的所有组件。 angular.io/docs/ts/latest/cookbook/…入口组件-
这适用于使用 ViewContainerRef.createComponent()
添加的动态添加的组件。将它们添加到 entryComponents
告诉离线模板编译器编译它们并为它们创建工厂。
路由配置中注册的组件也会自动添加到 entryComponents
,因为 router-outlet
还使用 ViewContainerRef.createComponent()
将路由组件添加到 DOM。
离线模板编译器 (OTC) 仅构建实际使用的组件。如果组件没有直接在模板中使用,OTC 就无法知道它们是否需要编译。使用 entryComponents,您可以告诉 OTC 也编译这些组件,以便它们在运行时可用。
What is an entry component? (angular.io)
定义在定义此组件时也应编译的组件。对于此处列出的每个组件,Angular 将创建一个 ComponentFactory 并将其存储在 ComponentFactoryResolver 中。
如果您没有在 entryComponents
中列出动态添加的组件,您将收到一条关于缺少工厂的错误消息,因为 Angular 不会创建一个。
另请参阅https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html
其他答案提到了这一点,但基本总结是:
在 html 中不使用组件时需要它,例如:
例如,使用 Angular Material Dialogs 您可以间接使用它们,它们是在 TS 代码而不是 html 中创建的:
openDialog() {
const dialogRef = this.dialog.open(MyExampleDialog, { width: '250px'});
}
这需要您将其注册为 entryComponent:
entryComponents:[MyExampleDialog]
否则你会得到一个错误:
ERROR 错误:未找到 MyExampleDialog 的组件工厂。你把它添加到@NgModule.entryComponents 了吗?
没有比 Angular 文档更好的解释了:entry-components 和 ngmodule-faq。
以下是角度文档的解释。
入口组件是 Angular 按类型强制加载的任何组件。通过其选择器以声明方式加载的组件不是入口组件。大多数应用程序组件都是以声明方式加载的。 Angular 使用组件的选择器来定位模板中的元素。然后它创建组件的 HTML 表示并将其插入到 DOM 中的选定元素处。这些不是入口组件。少数组件仅动态加载,从不在组件模板中引用。引导的根 AppComponent 是一个入口组件。没错,它的选择器匹配 index.html 中的元素标签。但是 index.html 不是组件模板,并且 AppComponent 选择器不匹配任何组件模板中的元素。 Angular 会动态加载 AppComponent,因为它要么在 @NgModule.bootstrap 中按类型列出,要么使用模块的 ngDoBootstrap 方法命令式地增强。路由定义中的组件也是入口组件。路由定义通过其类型引用组件。路由器忽略路由组件的选择器(如果它甚至有选择器)并将组件动态加载到 RouterOutlet 中。编译器无法通过在其他组件模板中查找这些入口组件来发现它们。您必须通过将它们添加到 entryComponents 列表来告诉它。 Angular 自动将以下类型的组件添加到模块的 entryComponents: @NgModule.bootstrap 列表中的组件。路由器配置中引用的组件。您不必明确提及这些组件,尽管这样做是无害的。
EntryComponent
的组件,我们应该删除 selector
属性吗? (因为它不会被使用)
从 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 注入令牌。
Ivy 是 Angular 下一代编译和渲染管道的代号。在 Angular 9 版本中,默认使用新的编译器和运行时指令,而不是旧的编译器和运行时指令,即 View Engine。
entryComponents 数组用于仅定义在 html 中找不到并动态创建的组件。 Angular 需要这个提示来查找入口组件并编译它们。
入口组件有两种主要类型:
引导的根组件。
您在路由定义中指定的组件。
有关入口组件的更多详细信息,请参阅 angular.io https://angular.io/guide/entry-components
在 Angular 13.1 中,不推荐使用 EntryComponent。参考:https://github.com/angular/angular/blob/master/CHANGELOG.md#1310-2021-12-09
关于 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);
entryComponents
,您可以告诉 OTC 也编译这些组件,以便它们在运行时可用。declarations
中,它也应该列在entryComponents
中,对吧?createComponent
动态添加组件时,或者例如也使用 thod API 添加组件的路由器。