NgModule中的声明,提供程序和导入之间有什么区别?


Answers:


516

角度概念

  • imports 使其他模块的导出声明在当前模块中可用
  • declarations使当前模块中的指令(包括组件和管道)可用于当前模块中的其他指令。指令,组件或管道的选择器只有在声明或导入时才与HTML匹配。
  • providers将使DI(依赖注入)知道服务和价值。它们被添加到根范围,并且被注入到其他具有它们依赖关系的服务或指令中。

providers延迟加载的模块有其自己的子注入器,这是一种特殊情况。providers默认情况下,仅向该延迟加载的模块提供延迟加载模块中的一个(而不是像其他模块一样整个应用程序)。

有关模块的更多详细信息,另请参见https://angular.io/docs/ts/latest/guide/ngmodule.html

  • exports使组件,指令和管道在将此模块添加到的模块中可用importsexports还可以用于重新导出模块,例如CommonModule和FormsModule,这通常是在共享模块中完成的。

  • entryComponents注册要脱机编译的组件,以便它们可以与一起使用ViewContainerRef.createComponent()。路由器配置中使用的组件是隐式添加的。

TypeScript(ES2015)导入

import ... from 'foo/bar'可能解析为index.ts)用于TypeScript导入。每当在另一个打字稿文件中声明的打字稿文件中使用标识符时,都需要这些。

Angular @NgModule() imports和TypeScript import完全不同的概念

另请参见jDriven-TypeScript和ES6导入语法

它们中的大多数实际上都是TypeScript也使用的普通ECMAScript 2015(ES6)模块语法。


1
我认为,但我不确定,最新建议是将应用程序范围的提供程序放在CoreModule中,而不是forRoot()在延迟加载的模块中使用。你同意吗?请参阅核心模块。到#shared-for-root的链接不再存在。
Mark Rajcok '16

1
很好的解释。谢谢@günter-zöchbauer。仅提及afaik import是JS(ES2015)功能,而不是 TypeScript 功能。:)
cassi.lup

什么是NgModule中的export []像出口一样糟:[MatCheckBox]
Omar Isaid 18'Sep

4
老实说,我认为Angular的NgModule的设计与VueReact相比笨拙而晦涩。您需要使用导入其他模块imports,但需要使用导出您的声明(组件,指令,管道)exports。因此,主要的目标imports,并exports为不同的东西。相反,您的主要目标exportsdeclarations。您可以通过声明组件declarations,但对于动态加载的组件,则需要将它们放入entryComponents。同时,providersDI由另一个故事管理。
xuemind

1
一个令人费解的答案,描述了一个令人费解的框架
Donato

85

imports 用于导入支持模块,例如FormsModule,RouterModule,CommonModule或任何其他定制功能模块。

declarations用于声明属于当前模块的组件,指令,管道。声明中的每个人都是彼此认识的。例如,如果我们有一个组件,例如UsernameComponent,它显示用户名列表,并且我们还有一个管道,例如toupperPipe,它将管道转换为大写字母字符串。现在,如果要在UsernameComponent中以大写字母显示用户名,则可以使用之前创建的toupperPipe,但问题是UsernameComponent如何知道toupperPipe存在以及如何访问和使用它。这里是声明,我们可以声明UsernameComponent和toupperPipe。

Providers 用于注入模块中的组件,指令,管道所需的服务。


3
“声明:用于声明属于当前模块的组件,指令,管道。声明中的所有内容相互了解。” 这应该是公认的答案
Deen John

60

声明了组件,导入了模块,并提供了服务。我正在使用的示例:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';


import { AppComponent } from './app.component';
import {FormsModule} from '@angular/forms';
import { UserComponent } from './components/user/user.component';
import { StateService } from './services/state.service';    

@NgModule({
  declarations: [
    AppComponent,
    UserComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [ StateService ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

3
我喜欢这种解释的简单性,但是让我感到奇怪的是,为什么不只有一个“ stuffsThisComponentNeeds”属性?似乎它们都在处理同一件事,这使其他代码段可用于当前组件。
redOctober13 '19

1
@ redOctober13我同意。例如,在Node.js中,无论是数据库模型,模块,服务还是已安装的第三方软件包,所有内容均以相同的方式导入。我认为reactJS
也是如此-SanSolo

18

角度@NgModule构造:

  1. import { x } from 'y';:这是ES2015/ES6用于从其他文件导入代码的标准打字稿语法(模块语法)。这不是特定于Angular的。从技术上讲,这也不是模块的一部分,仅需要在此文件的范围内获取所需的代码。
  2. imports: [FormsModule]:您可以在此处导入其他模块。例如,我们FormsModule在下面的示例中导入。现在,我们可以在整个模块中使用FormsModule必须提供的功能。
  3. declarations: [OnlineHeaderComponent, ReCaptcha2Directive]:您将组件,指令和管道放在此处。一旦在这里声明,您现在就可以在整个模块中使用它们。例如,我们现在可以OnlineHeaderComponentAppComponent视图(html文件)中使用。Angular知道在哪里可以找到它,OnlineHeaderComponent因为它是在中声明的@NgModule
  4. providers: [RegisterService]:此处定义了我们对这个特定模块的服务。您可以通过依赖注入来注入组件中的服务。

示例模块:

// Angular
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

// Components
import { AppComponent } from './app.component';
import { OfflineHeaderComponent } from './offline/offline-header/offline-header.component';
import { OnlineHeaderComponent } from './online/online-header/online-header.component';

// Services
import { RegisterService } from './services/register.service';

// Directives
import { ReCaptcha2Directive } from './directives/re-captcha2.directive';

@NgModule({
  declarations: [
    OfflineHeaderComponent,,
    OnlineHeaderComponent,
    ReCaptcha2Directive,
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
  ],
  providers: [
    RegisterService,
  ],
  entryComponents: [
    ChangePasswordComponent,
    TestamentComponent,
    FriendsListComponent,
    TravelConfirmComponent
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

10

添加快速备忘单,这可能对Angular长期休息后有所帮助:


声明

例:

declarations: [AppComponent]

我们可以在这里注入什么?组件,管道,指令


进口商品

例:

imports: [BrowserModule, AppRoutingModule]

我们可以在这里注入什么?其他模块


供应商

例:

providers: [UserService]

我们可以在这里注入什么?服务


自举

例:

bootstrap: [AppComponent]

我们可以在这里注入什么?此模块将生成的主要组件(组件树的顶级父节点)


输入组件

例:

entryComponents: [PopupComponent]

我们可以在这里注入什么?动态生成的组件(例如,通过使用ViewContainerRef.createComponent())


出口

例:

export: [TextDirective, PopupComponent, BrowserModule]

我们可以在这里注入什么? 我们想要在另一个模块中访问它们的组件,指令,模块或管道(在导入此模块之后)


1
出口呢?
lugte098

@ lugte098我已将导出添加到此列表中
PrzemekStruciński19年

我喜欢这种布局作为解释,非常易于理解。谢谢!
亚伦·乔丹

1
  1. 声明:此属性说明了属于该模块的组件,指令和管道。
  2. 出口:报关,应该在其他NgModules的分量模板可见的和可用的子集。
  3. imports:此NgModule中声明的组件模板需要其导出类的其他模块。
  4. provider:此NgModule为全球服务集合做出贡献的服务的创建者;它们可以在应用的所有部分中访问。(您也可以在组件级别指定提供程序,这通常是首选。)
  5. bootstrap:主应用程序视图,称为根组件,它承载所有其他应用程序视图。只有根NgModule才能设置bootstrap属性。
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.