AppModule中导入的模块在不同模块中不可见

时间:2019-10-01 16:12:07

标签: angular

让我们说这是我的AppModule:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    MaterialModule,
    HomeModule
  ],
  exports: [
    MaterialModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

如您所见,我在MaterialModule上声明了HomeModule,然后导出了MaterialModule。 但是仍然在HomeModule中,我无法使用MaterialModule中的组件,错误:

1. If 'mat-icon' is an Angular component, then verify that it is part of this module.
2. If 'mat-icon' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. 

因此,我不得不再次在MaterialModule中导入HomeModule。这是正确的行为还是我做错了什么?


我按照@ maryrio7的建议更改了AppModule中的Imports,现在是MaterialModule.forRoot(),并且向MaterialModule添加了静态方法,仍然无法使用。

@NgModule({
    imports: [
        MatButtonModule,
        MatCardModule,
        MatIconModule,
    ],
    exports: [
        MatButtonModule,
        MatCardModule,
        MatIconModule
    ]
})
export class MaterialModule {
    static forRoot(): ModuleWithProviders {
        return {
            ngModule: MaterialModule,
            providers: []
        };
    }
}

3 个答案:

答案 0 :(得分:2)

嗯... Angular中的一个常见误解是在父模块(即您的示例中为AppModule)中导入模块会创建模块的层次结构。因此,人们认为AppModule的子模块(即HomeModule)应该也继承父模块的导入模块。

但是,事实并非如此。模块不会继承对在父模块中声明的模块的访问。将模块想象成一个盒子。一个盒子将只包含您放入其中的所有内容。

现在,如果您有3个盒子,即盒子A,盒子M和盒子H。如果您没有将盒子M放在盒子H内,为什么盒子H包含属于盒子M的东西?

类似地,如果您将盒子M和盒子H放在盒子A内。现在,盒子A肯定会同时包含盒子M和盒子H中的所有东西,不是吗?

现在,将术语“盒子”切换为模块,将A切换为AppModule,将M切换为MaterialModule,将H切换为HomeModule。现在更有意义了吗?

要在Angular应用程序中进一步强调这一点,这就是为什么在生成新模块时会在新模块中自动导入CommonModule的原因。 CommonModule是BrowserModule的“较小”版本,包含组件中常用的NgIf,NgFor等指令。因为在新模块中,BrowserModule不会自动继承到其中-ngIf,ngFor等将不起作用。您可以通过删除CommonModule进行测试,看看是否可以使用ngFor,ngIf等。


您可以通过创建SharedModule来导入所有第三方lib的模块来轻松解决此问题。即导入MaterialModule,然后将其导出。

然后,所有(延迟加载的)功能模块都必须导入一个SharedModule,而不必重复对第三方模块的所有导入。

例如共享模块

@NgModule({
   imports:[
       CommonModule, FormsModule, ReactiveFormsModule, MaterialModule, 
       //... {other modules that will be shared between modules} ...,
   ],
    exports:[
        CommonModule, FormsModule, ReactiveFormsModule, MaterialModule,
        //... {other modules that will be shared between modules} ...,
    ]
})

答案 1 :(得分:1)

最好使用SharedModule,然后将其导入到要使用其模块之一的位置:

  

创建共享模块可以使您组织和简化代码。您可以将常用的指令,管道和组件放入一个模块,然后在需要的其他位置将其仅导入应用程序的其他部分。

@NgModule({
    imports:      [ MaterialModule],
    exports:      [ MaterialModule ]
})
export class SharedModule { }

现在,您可以在HomeModule中的任意位置注入SharedModule:

@NgModule({
    imports:      [ SharedModule ] // <-- now you can access MaterialModule
})
export class HomeModule { }

答案 2 :(得分:0)

我认为如果要跳过导入步骤,则必须将forRoot()添加到模块中,如下所示:

imports: [
    .....
    MaterialModule.forRoot(),
    ....
  ],

编辑: 尝试将其添加到您的 MaterialModule.ts

@NgModule({
  exports: [MaterialModule]
})
export class MaterialModule { }