You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 6如何从懒加载模块中加载并显示组件?

解决Angular 6懒加载库组件无法通过MatDialog打开的问题

我之前也碰到过类似的Angular懒加载库组件配合MatDialog使用的坑,你的思路方向是对的,只是没get到懒加载模块的核心细节:懒加载模块会创建独立的模块引用(NgModuleRef),它的组件工厂只存在于自身的ComponentFactoryResolver中,根模块的注入器和组件工厂池根本找不到这些组件。下面给你两种可行的解决方案:

方案一:直接从懒加载模块引用中获取组件工厂

这个方案是基于你现有代码的改造,核心是拿到懒加载模块的组件解析器,再用它来获取目标组件的工厂,最后传给MatDialog。

步骤1:保存懒加载模块的引用

修改你在AppComponent里的load()方法,把创建好的模块引用保存下来:

import { NgModuleRef } from '@angular/core';

// 新增变量保存模块引用
private chatModuleRef: NgModuleRef<any>;

constructor(private _injector: Injector, private loader: SystemJsNgModuleLoader, public dialog: MatDialog) {}

load() {
  this.loader.load('dist/org/chat#ChatModule').then(moduleFactory => {
    // 保存模块引用
    this.chatModuleRef = moduleFactory.create(this._injector);
  });
}

步骤2:用模块内的组件工厂打开对话框

新增打开对话框的方法,从保存的模块引用中获取组件工厂,再传给MatDialog:

openChatPopup() {
  // 先判断模块是否已加载
  if (!this.chatModuleRef) {
    alert('请先加载聊天模块');
    // 或者自动触发加载:this.load().then(() => this.openChatPopup());
    return;
  }

  // 从懒加载模块中获取组件解析器
  const resolver = this.chatModuleRef.componentFactoryResolver;
  // 获取ChatPopupComponent的组件工厂
  const chatPopupFactory = resolver.resolveComponentFactory(ChatPopupComponent);

  // 用组件工厂打开对话框
  const dialogRef = this.dialog.open(chatPopupFactory, {
    data: {}
  });
}

方案二:封装成模块内服务(更优雅)

如果想让主应用完全不用关心懒加载的细节,可以在你的@org/chat库中封装一个服务,专门负责加载模块和打开对话框,这样主应用只需要调用服务方法即可。

步骤1:在ChatModule中创建ChatService

import { Injectable, Inject, NgModuleRef, ComponentFactoryResolver } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { SystemJsNgModuleLoader, SYSTEM_JS_NG_MODULE_LOADER } from '@angular/core';
import { ChatPopupComponent } from './chat-popup.component';

@Injectable({
  providedIn: 'root' // 或者在ChatModule的providers中声明
})
export class ChatService {
  private chatModuleRef: NgModuleRef<any>;

  constructor(
    private dialog: MatDialog,
    private injector: Injector,
    @Inject(SYSTEM_JS_NG_MODULE_LOADER) private loader: SystemJsNgModuleLoader
  ) {}

  async openChatDialog() {
    // 懒加载模块(仅第一次加载)
    if (!this.chatModuleRef) {
      const moduleFactory = await this.loader.load('dist/org/chat#ChatModule');
      this.chatModuleRef = moduleFactory.create(this.injector);
    }

    // 获取组件工厂并打开对话框
    const resolver = this.chatModuleRef.componentFactoryResolver;
    const factory = resolver.resolveComponentFactory(ChatPopupComponent);
    this.dialog.open(factory, { data: {} });
  }
}

步骤2:主应用中调用服务

在AppComponent中注入ChatService,直接调用方法即可:

constructor(private chatService: ChatService) {}

openChat() {
  this.chatService.openChatDialog();
}

关键注意事项

  • 确保ChatPopupComponent在ChatModule的declarations和entryComponents中声明(Angular 6必须加entryComponents,Angular 9+可以省略,但为了兼容建议加上),并且要在模块中导出该组件:
    @NgModule({
      declarations: [ChatPopupComponent],
      entryComponents: [ChatPopupComponent],
      exports: [ChatPopupComponent]
    })
    export class ChatModule {}
    
  • 不要在AppModule中导入ChatModule,否则就失去了懒加载的意义。

为什么你之前的方法不行?

  • 直接导入组件:因为AppModule没有导入ChatModule,Angular编译器无法识别该组件所属的模块,所以报错“Component is not part of any NgModule”。
  • 用字符串名称打开:MatDialog默认会去根注入器的ComponentFactoryResolver中查找组件工厂,而懒加载模块的组件工厂只存在于自身的模块引用中,根注入器根本找不到,所以报错“No component factory found”。

内容的提问来源于stack exchange,提问作者dev7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:08:22