声明和entryComponents有什么区别


72

我的app.module.ts中有这个:

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { HttpModule, Http } from '@angular/http';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { EliteApi } from '../shared/shared';
import { MyApp } from './app.component';
import { MyTeams, Tournaments, TeamDetails, Teams, TeamHome, Standings } from '../pages/pages';

import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

@NgModule({
    declarations: [
        MyApp,
        MyTeams,
        TeamDetails,
        Tournaments,
        Teams,
        TeamHome,
        Standings
    ],
    imports: [
        BrowserModule,
        IonicModule.forRoot(MyApp),
        HttpModule
    ],
    bootstrap: [IonicApp],
    entryComponents: [
        MyApp,
        MyTeams,
        TeamDetails,
        Tournaments,
        Teams,
        TeamHome,
        Standings
    ],
    providers: [
        HttpModule,
        StatusBar,
        SplashScreen,
        { provide: ErrorHandler, useClass: IonicErrorHandler },        
        EliteApi
    ]
})
export class AppModule { }

目前,我declarationsentryComponents两者完全相同。它们包含我为我的应用程序构建的所有页面/组件。如果我从任何属性中删除任何条目,我会在angular2中收到错误消息。

我的问题是,如果它们始终相同,那么对这些属性的需求是什么?我想我肯定在这里缺少一点。什么时候entryComponents和声明会彼此不同?

Answers:


123

entryComponents阵列被用来定义未在HTML与发现和动态创建的部件ComponentFactoryResolver。Angular需要此提示来找到它们并进行编译。所有其他组件应仅在声明数组中列出。

这是角度网站上的文档


7
为什么以及何时EntryComponents在ngModule中使用property?目前尚不清楚,会更好,如果你添加一些更多的解释
Pardeep耆那教

2
@PardeepJain:我也偶然发现了同一问题。我添加了一个用例。我希望这也会对其他人有所帮助
Shashank Vivek

2
文档链接地址已更改,我猜为angular.io/guide/entry-components
Sunny Drall

可能是因为某个组件被放置在了entryComponents块中,不是因为它也没有被放置在declarations块中,而是因为我们希望对其进行预编译?
Stephane

entryComponents也用于自定义组件(Web组件)。我在文档中看到了!
ykadaru '19

34

@Julia已回答了这个问题。我想添加Modal的用例。


可以说,您有一个名为的组件ModalComponent。为了使其更可重用,您希望传递一个组件名称,并希望该组件在ModalComponent*内呈现。

示例module.ts如下:

import:[ModalModule],  // As a best practice, we can create Modal as a separate Feature
entryComponent : [TheCompYouWantToRenderInsideModalComponent]

我们会通过TheCompYouWantToRenderInsideModalComponententryComponent因为在编写网站代码时该组件将不存在(即,TheCompYouWantToRenderInsideModalComponent在任何HTML文件中都没有选择器)。我们将其传递component给Modal,然后在打开模式时动态地对其进行渲染。如下所示:

onSomeButtonClickToOpenModal(){
     this.modalService.openModal(TheCompYouWantToRenderInsideModalComponent);
}

*在中ModalModule,我们将创建要使用的服务ComponentFactoryResolver并将其TheCompYouWantToRenderInsideModalComponent作为参数。稍后,我们可以调用一个函数(称为openModal(componentType: ComponentType)),该函数将使用ComponentFactoryResolver


旁注:出于相同目的,entryComponent还将在Angular V6elements功能中发挥重要作用。

更新:Angular 9

有了Ivy编译器Angular 9发布后就不再需要了entryComponent


2
正是我要的东西,谢谢!
Nicwenda

2
@Nicwenda:谢谢:)我也很努力,觉得这个答案值得分享
Shashank Vivek

3
很棒的解释
user1312242

5

简而言之:

存在的“真正”原因entryComponents是摇树,而declarations主要是为了模块封装而存在。因此它们甚至不可比。如果摇晃不是我们关心的问题,那么将声明作为两个声明的唯一来源将是一件好事。

更长的答案

components您在自己创建的所有内容module都不会进入最终捆绑包。而是,仅将template使用selectorsOR声明的组件components添加到entryComponents数组(由您或框架)。

在动态创建组件时(如使用ComponentFactoryResolver已接受的答案所述),您可能希望添加组件。或者,当您在Route数组中声明组件或在其他命令式创建过程中,框架可以添加组件。

从官方文档:

实际上,许多库都声明和导出了您永远不会使用的组件。例如,材料设计库将导出所有组件,因为它不知道您将使用哪个组件。但是,您不太可能会全部使用它们。对于您不参考的组件,摇树器会将这些组件从最终代码包中删除。

如果组件不是入口组件,并且在模板中找不到,则摇树机会将其丢弃。因此,最好仅添加真正的入门组件,以帮助您的应用程序尽可能地精简。



1

为此,您需要了解在创建组件时,Angular在幕后实际上是如何工作的。

以及你打算与工作指令和管道的任何部分,你需要将它们添加到您的declarations阵列中@NgModuleapp.module.ts(同时有多个工作modules,我们导入了功能模块我们在app.module.ts imports阵列中,并且feature module拥有所有的组件及其declarations阵列)。

上面提到的步骤对于使角度了解应用程序中的组件或组件和指令很重要,因为它不会自动扫描所有文件。创建新组件后,您需要告诉它存在哪些组件。

尽管如此,仅此一项就只能使它对角度有所了解,以便在两个位置之一找到它时就能够创建这样的组件-

  1. 如果在角度模板中找到某个selector组件的a ,则第一个位置将在您的模板中->然后,它基本上会查看declarations该特定组件的数组->在此处找到并能够创建该组件。

  2. 其他地方的角度将寻找这个组件是你routs在你的rout config, - >当你指向一个组件有角也将检查在declarations阵列和- >如果发现有它能够创造这样的组件并加载它。

现在,默认情况下不起作用的一个地方是您想在代码中手动创建组件。就像当你想创建一个dynamic componentcomponent factory像一个alert component也许这只能说明了当有任何错误,你没有提到selector它在任何template也不在rout config

而现在,这里的angular不会自动到达声明数组。它根本不这样做。您可以对此抱怨。情况仍然如此。

相反,您需要故意通知角度,在这种情况下,将需要在某个位置创建警报组件,并且基本上应该为此准备角度。

一般而言,angular会在template或中找到一个组件时为该创建做准备rout config。但是在我们的情况下,由于如上所述的两件事我们都没有做,所以angular不会自己做准备。

现在就来告诉角度为创建该组件的做好准备,你需要一个特殊的属性添加到您传递给对象Ngmodule之外declarations import等。该属性是entry components,它是组件类型的数组,但是只有那些最终将在不使用routs或的情况下创建的组件selectors

但是随着Angular 9的发布,幕后进行了一些更改,并且为您完成了所有这些工作,您无需再entry components手动提及。

积分-从MaximilianSchwarzmüller的Udemy课程“ Angular the Complete Guide”中学习了这些概念。


1
最好的解释在这里!
Alma Z

0

入口组件是Angular强制性加载的任何组件,这意味着您没有按类型在模板中引用它。例如 :

@Component({
  selector: 'app-entry-component', // <== component select tags
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppEntryComponent {
  // <== Component Class
}

在您正在使用的组件中添加此选择器

<app-entry-component></app-entry-component>

在appmodule中添加此组件

const routes: Routes = [
  {
    path: '',
    component: ComponentClassName,
    children: []
  }
]

最后

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    ...
  ],
  providers: [],
  bootstrap: [AppComponent],
  entryComponents: [
    AppEntryComponent
  ]
})
export class AppModule { }

如果您也没有在溃败中提及这一点。
阿潘·班纳吉
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.