Angular微前端(MFE)调用对话框组件时MAT_DIALOG_DATA注入失败求助
解决Angular微前端中远程组件注入MAT_DIALOG_DATA失败的问题
问题场景
在Angular宿主应用中加载另一个Angular项目的远程模块,加载代码如下:
loadRemoteModule({ remoteEntry: 'https://localhost:3028/sremoteEntry.js', remoteName: 'mfe1', exposedModule: './MyModule', }) .then(m => { const myComponent= m.MyModule.ɵmod.declarations[0]; this._dialogRef = this._dialog.open(myComponent, { data: eeData, disableClose: false, width: '990px', height: '495px', autoFocus: false, }); return m.MyModule; })
远程组件的构造函数依赖@Inject(MAT_DIALOG_DATA) public dialogData: any,打开对话框时提示MdcDialogData未提供。已确认所有公共依赖均设置为singleton:true共享,且尝试过以下方案:
- 在远程模块和宿主模块中都引入MatDialogModule
- 静态提供
MAT_DIALOG_DATA(设置useValue: {})——此方案可行,但无法传递宿主端的eeData
解决方案
方案一:通过自定义注入器传递令牌
直接调用_dialog.open()传递data在微前端场景下会因为注入上下文隔离失效,需要手动创建组件工厂并提供令牌:
loadRemoteModule({ remoteEntry: 'https://localhost:3028/sremoteEntry.js', remoteName: 'mfe1', exposedModule: './MyModule', }) .then(async (m) => { // 编译并创建远程模块的NgModule实例 const moduleFactory = await this._compiler.compileModuleAsync(m.MyModule); const moduleRef = moduleFactory.create(this._injector); // 获取目标组件类 const myComponent = m.MyModule.ɵmod.declarations[0]; // 创建组件工厂 const componentFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(myComponent); // 构建包含MAT_DIALOG_DATA的自定义注入器 const injector = Injector.create({ parent: this._injector, providers: [ { provide: MAT_DIALOG_DATA, useValue: eeData } ] }); // 打开对话框时传入自定义注入器 this._dialogRef = this._dialog.open(myComponent, { data: eeData, // 保留此字段确保MatDialog内部逻辑兼容 disableClose: false, width: '990px', height: '495px', autoFocus: false, injector: injector // 关键:传递自定义注入器 }); return m.MyModule; })
方案二:直接暴露组件而非模块
如果远程模块仅需提供该对话框组件,可简化为直接暴露组件类,避免模块上下文的注入隔离问题:
- 修改远程模块的webpack配置,调整暴露内容:
module.exports = { // 其他配置... exposes: { './MyComponent': './src/app/my-component/my-component.component.ts' } };
- 宿主端加载代码调整为:
loadRemoteModule({ remoteEntry: 'https://localhost:3028/sremoteEntry.js', remoteName: 'mfe1', exposedModule: './MyComponent', }) .then(({ MyComponent }) => { // 构建包含MAT_DIALOG_DATA的自定义注入器 const injector = Injector.create({ parent: this._injector, providers: [ { provide: MAT_DIALOG_DATA, useValue: eeData } ] }); this._dialogRef = this._dialog.open(MyComponent, { data: eeData, disableClose: false, width: '990px', height: '495px', autoFocus: false, injector: injector }); })
关键注意事项
确保@angular/material相关包(尤其是@angular/material/dialog)在宿主和远程模块的webpack共享配置中均设置为singleton: true,避免因依赖重复实例化导致注入令牌不匹配。
内容的提问来源于stack exchange,提问作者Abhishek
相关产品推荐
相关产品推荐

