ChatGPT解决这个技术问题 Extra ChatGPT

Angular ngModule 中的 entryComponents 是什么?

我正在开发一个依赖于 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/…入口组件-

G
Günter Zöchbauer

这适用于使用 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 添加组件的路由器。
M
Mike R

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

在 html 中不使用组件时需要它,例如:

例如,使用 Angular Material Dialogs 您可以间接使用它们,它们是在 TS 代码而不是 html 中创建的:

openDialog() {
    const dialogRef = this.dialog.open(MyExampleDialog, { width: '250px'});
}

这需要您将其注册为 entryComponent:

entryComponents:[MyExampleDialog]

否则你会得到一个错误:

ERROR 错误:未找到 MyExampleDialog 的组件工厂。你把它添加到@NgModule.entryComponents 了吗?


最好的解释在这里。
很简单,谢谢。 XD
有时最简单的答案往往是最好的答案。
R
RonanCodes

没有比 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 列表中的组件。路由器配置中引用的组件。您不必明确提及这些组件,尽管这样做是无害的。


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

从 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。
V
Vivek

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

入口组件有两种主要类型:

引导的根组件。

您在路由定义中指定的组件。

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


N
Nipuna

关于 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);