Angular2 应用程序模块,具有根级别导入

17

根据我的理解,根级别的导入应该是全局可用的(当我说全局时,指的是所有子模块和组件)。

我有以下的根/应用程序模块:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ApplicationRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';
import { appRouterProviders, routing } from './app.routes';
import { DashboardModule } from './dashboard/dashboard.module';
import { DecisionModule } from './decision/decision.module';
import { MdCoreModule }           from '@angular2-material/core';
import { MdButtonModule }         from '@angular2-material/button';
import { MdCardModule }           from '@angular2-material/card';
import { MdListModule }           from '@angular2-material/list';
import { MdSidenavModule }        from '@angular2-material/sidenav';
import { MdToolbarModule }        from '@angular2-material/toolbar';
import { MdIconModule }           from '@angular2-material/icon';

@NgModule({
  declarations: [
    AppComponent                    
  ],
  imports: [
    BrowserModule,
    CommonModule,
    FormsModule,
    HttpModule,
    RouterModule,    
    routing,
    DashboardModule,
    MdCoreModule,
    MdButtonModule,
    MdCardModule,
    MdListModule,
    MdSidenavModule,    
    MdToolbarModule,
    MdIconModule
  ],
  providers: [
    appRouterProviders
  ],
  entryComponents: [ AppComponent ],
  bootstrap: [ AppComponent ]
})
export class AppModule {

}

如果我尝试在我的一个子模块中使用材料元素,它们不会显示出来,这是该子模块的样子:

import { NgModule }               from '@angular/core';
import { CommonModule }           from '@angular/common';
import { FormsModule }            from '@angular/forms';
import { dashboardRouting }       from './dashboard.routes';
import { DashboardComponent }     from './dashboard.component';
import { ActionsDialogComponent } from './actions-dialog';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    dashboardRouting,    
  ],
  declarations: [
    DashboardComponent,
    ActionsDialogComponent    
  ],
  providers: [    
  ]
})
export class DashboardModule {}

然而,如果我在子模块中导入材料模块,它们就会显示出来。当材料设计组件正常工作时,该子模块的外观如下:

import { NgModule }               from '@angular/core';
import { CommonModule }           from '@angular/common';
import { FormsModule }            from '@angular/forms';
import { dashboardRouting }       from './dashboard.routes';
import { DashboardComponent }     from './dashboard.component';
import { ActionsDialogComponent } from './actions-dialog';
import { MdCoreModule }           from '@angular2-material/core';
import { MdButtonModule }         from '@angular2-material/button';
import { MdCardModule }           from '@angular2-material/card';
import { MdListModule }           from '@angular2-material/list';
import { MdSidenavModule }        from '@angular2-material/sidenav';
import { MdToolbarModule }        from '@angular2-material/toolbar';
import { MdIconModule }           from '@angular2-material/icon';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    dashboardRouting,
    MdCoreModule,
    MdButtonModule,
    MdCardModule,
    MdListModule,
    MdSidenavModule,    
    MdToolbarModule,
    MdIconModule,
  ],
  declarations: [
    DashboardComponent,
    ActionsDialogComponent    
  ],
  providers: [    
  ]
})
export class DashboardModule {}
为什么如果材料模块已经在根级别导入了,那么它们必须再次在子级别上导入呢?

为什么如果材料模块已经在根级别导入了,那么它们必须再次在子级别上导入呢?


2
你的模块应该是可重用的。为什么使用你的模块的人需要导入各种模块到他的根模块呢?这只会使你的模块更难以重复使用。 - Günter Zöchbauer
哦,等等……那是真的。谢谢。 - Werner Swart
2个回答

51

Angular的文档有些令人困惑,它们在几个地方说明你在根模块(app.module.ts)导入的模块是全局可用的,但是除非你深入阅读(blah),否则很难直观地发现当你使用子模块时会破坏这种继承关系,并且子模块为组件创建了自己的应用程序域(服务不受影响,至少我是这样理解的)。这也是为什么如果像我一样,我注意到有些东西必须导入到我的子模块中,而其他一些则不需要,这让我非常困惑。这里是angular.io上讨论此问题的部分:NgModule.html

还有一点值得一提:我以为在 Angular2 RC5+ 之后开发意味着我需要将所有功能封装到模块中,其实并非如此。在我们日常使用 Angular2 开发中,除非你想要使用懒加载或特别希望与他人共享代码(例如一个 npm 包),否则模块对我们的构建并不是必须的。


我注意到我的子模块中需要导入一些项目,而另一些则不需要,这让我很困惑。这个问题困扰了我很长时间。好的解释可以帮助我理解。 - ceebreenk
1
我的脑袋炸了,这真是太棒了!在尝试使用Angular Material模块时,这让我省去了很多麻烦。谢谢! - chesscov77
谢谢您的解释。我卡在这里已经好几天了。在将声明从全局移动到模块级别后,它终于起作用了。 - B G Kavinga
这在2022年的Angular 10构建中帮了我很多。非常感谢。 - gslette

9
在Angular2的组件概念中,没有像你所说的“根级别”的概念。
组件类似于Java(或其他高级语言)项目中的类,是模块化的组件,您需要导入每个使用的类。
它们可以嵌套或互相使用,但仍然每个组件都需要导入自己的依赖项。
请注意,在Angular2中导入是一种非常不同的方法,与在Angular 1中包括外部模块/库有很大区别(那时每个依赖项基本上是在index.html中添加一个新的引用)。
这些Angular 2的导入首先存在是因为Typescript编译器需要知道您的组件中使用了什么(从而提供更多的错误检查能力)。
编译和打包构建应该只包含每个依赖项一次(如果一切都配置正确的话)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接