Angular 6特性模块中使用Angular Material的问题与最佳实践
解决懒加载特性模块中使用Angular Material的问题
我之前在Angular懒加载项目里用Material组件也踩过类似的坑,来给你捋捋正确的实现方式和最佳实践,顺便帮你排查之前的问题:
你遇到的Uncaught (in promise): TypeError: Cannot read property 'call' of undefined错误,大概率是重复导入Material模块导致的依赖冲突,或是缺少了Angular Material必需的动画模块。下面是规范的解决方案:
最佳实践:创建Shared Material模块
在多模块项目里,最省心的方式是做一个共享的Material模块,统一管理所有要用到的Material组件模块,既避免重复导入,也方便后续维护。
1. 新建共享Material模块
在app目录下创建shared/material/material.module.ts,代码如下:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; // 导入你需要的Material组件模块,这里以MatButton为例 import { MatButtonModule } from '@angular/material/button'; // 如果后续要加其他组件(比如MatCard、MatInput),直接在这里导入即可 @NgModule({ declarations: [], imports: [ CommonModule, // 导入目标Material组件模块 MatButtonModule ], // 关键步骤:把导入的Material模块导出,这样其他模块导入这个共享模块就能用这些组件 exports: [ MatButtonModule ] }) export class MaterialModule { }
2. 在根模块(app.module.ts)中添加基础依赖
Angular Material必须依赖BrowserAnimationsModule才能正常工作,一定要在根模块里导入它:
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; // ...其他必要导入 @NgModule({ imports: [ BrowserModule, BrowserAnimationsModule, // 这个是Material组件生效的前提 AppRoutingModule, // 根模块不需要导入MaterialModule,除非根组件要用到Material组件 ], // ...其他配置 }) export class AppModule { }
3. 在特性模块中导入共享Material模块
比如在homepage.module.ts里,只需要导入我们刚创建的MaterialModule:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { HomepageRoutingModule } from './homepage-routing.module'; import { HomepageComponent } from './pages/homepage.component'; // 导入共享的Material模块 import { MaterialModule } from '../../shared/material/material.module'; @NgModule({ declarations: [HomepageComponent], imports: [ CommonModule, HomepageRoutingModule, MaterialModule // 导入后,组件里就能直接用MatButton了 ] }) export class HomepageModule { }
把同样的操作复制到inbox.module.ts里,两个懒加载模块就都能正常使用MatButton了。
为什么你之前的方法会出错?
- 多个特性模块重复导入
MatButtonModule:Angular的模块机制下,重复导入同一模块(尤其是懒加载模块)很容易引发依赖注入冲突,就会出现你遇到的Cannot read property 'call' of undefined错误。 - 根模块导入
MatButtonModule却无效:懒加载模块是独立的模块单元,根模块导入的模块不会自动传递给懒加载模块,懒加载模块必须自行导入所需的依赖模块。
额外注意事项
- 确保Material版本和Angular 6兼容:Angular 6对应的Material版本是6.x.x,执行
npm install @angular/material@6.x.x @angular/cdk@6.x.x可以安装匹配版本,版本不匹配也会触发各种奇怪错误。 - 如果某个Material组件只在单个特性模块里使用,也可以直接在该模块里导入对应的Material组件模块,但共享模块的方式更适合多模块共用组件的场景,便于统一管理。
内容的提问来源于stack exchange,提问作者KevinTale
相关产品推荐
相关产品推荐

