【问题标题】:How to correctly import the Angular Material module through a shared module in Angular 4?如何通过 Angular 4 中的共享模块正确导入 Angular Material 模块?
【发布时间】:2017-11-29 01:20:37
【问题描述】:

我正在使用 Angular 和 Angular Material 构建应用程序,但我的模块结构存在一些问题。

正如指导方针所建议的那样,导入 MaterialModule 已被弃用,不应再进行,这就是为什么我制作了一个单独的 MaterialModule,我只导入我需要使用的 Material 模块;然后将此模块导入到 SharedModule 中,该模块最终会在需要的任何地方导入,包括主 AppModule。

我正在使用的 Material 组件之一是 MdTooltip,除了我在平板电脑上测试我的应用程序时,它一切正常:发生的情况是,工具提示不会像预期的那样对长按做出反应到,他们不会打开。我设法使它工作的唯一方法是在我的 AppModule 中导入完整的 MaterialModule(来自 @angular/material),这是非常错误和不雅的。任何其他方法似乎都无法解决问题,因为它们都会带来自己的问题,同时无法解决问题。

这些是我的模块(去掉了多余的导入语句):

材料模块:

import { NgModule } from '@angular/core';
import {...} from '@angular/material';

@NgModule({
  imports: [
    MdGridListModule,
    MdButtonModule,
    MdTabsModule,
    MdToolbarModule,
    MdCardModule,
    MdInputModule,
    MdSelectModule,
    MdAutocompleteModule,
    MdIconModule,
    MdTooltipModule
  ],
  exports: [
    MdGridListModule,
    MdButtonModule,
    MdTabsModule,
    MdToolbarModule,
    MdCardModule,
    MdInputModule,
    MdSelectModule,
    MdAutocompleteModule,
    MdIconModule,
    MdTooltipModule
  ],
  providers: [
    MdIconRegistry
  ]
})

export class MaterialModule {}

共享模块:

import { MaterialModule } from '../material/app-material.module';
@NgModule({
  imports:      [
    CommonModule,
    MaterialModule,
    FlexLayoutModule,
    FormsModule,
    ReactiveFormsModule
  ],
  declarations: [
    NavbarComponent,
    SearchFiltersComponent,
    RightCurrencyPipe
  ],
  exports:      [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    MaterialModule,
    FlexLayoutModule,
    NavbarComponent,
    RightCurrencyPipe,
    SearchFiltersComponent
  ],
  providers: [
    SpinnerService,
    ProductsService,
    StatePersistenceService
  ]
})

export class SharedModule {}

应用模块:

import { MaterialModule } from "@angular/material";
@NgModule({
  declarations: [
    AppComponent,
    ProductPageComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    RouterModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    SharedModule,
    CoreModule,
    LoginModule,
    MaterialModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

我做错了吗?您将如何将您的应用程序划分为子模块?

提前致谢

【问题讨论】:

  • 我做了和你一样的事情,但是我得到了“StaticInjectorError[ElementRef]:”错误,所有东西都加载了,但是角材料组件不起作用。你知道为什么吗?

标签: angular typescript angular-material2


【解决方案1】:

根据您的编译和部署策略,您可能希望使用摇树(用于消除死代码或实时代码导入)。这是MaterialModule 被弃用的主要动机。官方建议是在需要的模块中only import the components you need。您使用所有导入创建单个 MaterialModule 的解决方案正在撤消该方面,但可能会根据您的项目结构起作用(例如,如果您只使用单个模块)。

尝试从您的 SharedModule 导出中删除 MaterialModule。这样,您的应用根目录中的模块只有一个入口点。

【讨论】:

  • 那是一个有见地的答案,但是我最初的问题未能解决一些问题。 SharedModule 声明和导出的组件广泛使用了 Material 组件,这使得导入我的 MaterialModule(或单个组件,就此而言)是必要的;但是,工具提示不能正常工作。使它起作用的原因是在我的 AppModule 中导入已弃用的 MaterialModule,同时将我的自定义 MaterialModule 导入到我的 SharedModule 中。为什么我需要在根目录下导入完整的 MaterialModule?这就是我的烦恼
  • 您可能想要检查 node_modules 中已安装的版本:已弃用的 MaterialModule 不应该对最新版本做任何事情。如我所见,SharedModule 中有两个组件,AppModule 中有两个组件(将它们放在自己的模块中是recommend)。如果您没有从SharedModule 导出并在您的AppModule 中导入了您的组件所需的特定组件(AppComponentProductPageComponent)怎么办?
  • 你说得对,弃用的 MaterialModule 基本上什么都不做,只是一个空类。我已经尝试在每个模块中导入我需要的所有单个模块,并且除了工具提示触摸功能之外一切正常。出于某种原因,使其工作的唯一方法是在我的主 AppModule 中导入已弃用的 MaterialModule,无论我做什么。如果我导入它,我会得到触摸功能,如果我不导入它,它就不起作用。这对我来说没有多大意义,老实说,这可能取决于hammer.js和BrowserModule的导入位置吗?
【解决方案2】:

你的方法很棒。您提供的结构是 material.angular.io 中提供的替代方案。我不确定为什么您的工具提示不起作用。但我想建议您只在根模块上使用您的自定义 MaterialModule 一次。无需在 SharedModule 中再次导入。

【讨论】:

    【解决方案3】:

    您的第一个错误是 SharedModule 中的服务。 SharedModule 不应该有 Providers 数组。 CoreModule 用于服务。

    您不需要导入共享模块中的所有内容。 SharedModule 通常用于导出。 MaterialModule 也不需要导入,因为它不使用它们。它的目的是出口。

    如果 NavBarComponent 在应用范围内使用,那么它应该在 CoreModule 中。不在 SharedModule 中。

    如果您不需要,请不要将 SharedModule 导入 AppModule。 SharedModule 用于 FeaturedModules。

    阅读官方文档:https://angular.io/guide/ngmodule-faq#what-kinds-of-modules-should-i-have-and-how-should-i-use-them

    【讨论】:

    • 为什么 SharedModule 不应该有任何提供者?如果我想为每个功能提供新服务怎么办?那有什么问题?
    • 如果你有一个特定功能的服务,你应该把它放在那个功能模块中。不在共享模块中。共享模块适用于所有人。
    • 想解释一下你的陈述吗?
    【解决方案4】:
    1. 在“src\app”中创建一个共享模块,使用:ng g module shared

    2. 在共享模块中导入所有需要的材料模块。重要的!!!如果您尝试将一组模块一起导入,有时会出现错误。你应该像下面这样一个一个地导入它们=>

      从'@angular/material/button'导入{ MatButtonModule };

      从“@angular/material/form-field”导入 {MatFormFieldModule};

      从“@angular/material/input”导入 {MatInputModule};

    然后

        @NgModule({
      declarations: [],
      imports: [
        CommonModule,
        MatButtonModule,
        MatFormFieldModule,
        MatInputModule
      ],
      exports: [
        MatButtonModule,
        MatFormFieldModule,
        MatInputModule
    
      ]
    })
    

    现在您可以在任何需要您在 shared module 中导入的一个或多个材料模块的地方导入此共享模块。 例如,如果您在学生示例中需要有角度的材料 =>

    import {SharedModule} from '../shared/shared.module'
    

    然后

    @NgModule({
      declarations: [
        TdFormComponent],
      imports: [
        CommonModule,
        SharedModule,
        
      ]
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-21
      • 2019-09-04
      • 2020-05-25
      • 1970-01-01
      • 2020-09-29
      • 2020-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多