如何在没有路由器的情况下动态延迟加载模块-Angular 9



我有几个模块想要动态延迟加载,我正在从v8升级到v9,随着angular的版本9,有关模块的逻辑似乎已经改变。最好的方法是什么?

  1. 不带模块的组件

如果我们想动态延迟加载组件(没有模块(,那么我们可以使用与路由相同的模式:

// <ng-template #myContainer></ng-template>    
@ViewChild('myContainer', { read: ViewContainerRef }) container: ViewContainerRef;

const { MyLazyComponent } = await import('./path/to/lazy/component');
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(MyLazyComponent);
const { instance } = this.container.createComponent(componentFactory);
  1. 模块

如果组件依赖于其他服务/组件,那么我们需要加载完整的模块。因为它将被延迟加载(最初未编译(,所以我们需要运行编译";"手动";。它仍然比以前版本的Angular上使用的技巧更容易。这里有一个解决方案。

我们可以创建一个存储模块引用的服务,并将组件加载到容器中(给定模块ID和容器引用(。

import { Injectable, Compiler, Injector } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LazyComponentService {
private componenttRefs = {
myFirstLazyModuleId: import('../path/to/first/lazy/module/component.module'),
mySecondLazyModuleId: import('../path/to/second/lazy/module/component.module')
};
constructor(
private compiler: Compiler,
private injector: Injector,
) { }
async loadComponent(moduleId, container) {
let ref;
try {
const moduleObj = await this.componenttRefs[moduleId];
const module = moduleObj[Object.keys(moduleObj)[0]];
const moduleFactory = await this.compiler.compileModuleAsync(module);
const moduleRef: any = moduleFactory.create(this.injector);
const componentFactory = moduleRef.instance.resolveComponent();
ref = container.createComponent(componentFactory, null, moduleRef.injector);
} catch (e) {
console.error(e);
}
return ref;
}
}

模块需要编译。我们通过在每个模块的构造函数中调用resolveComponentFactory来实现这一点:

@NgModule({
imports: [
MyModules...
],
declarations: [
MyFirstLazyComponent
]
})
export class MyFirstLazyComponentModule {
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
public resolveComponent(): ComponentFactory<MyFirstLazyComponent> {
return this.componentFactoryResolver.resolveComponentFactory(MyFirstLazyComponent);
}
}

然后神奇的是,你可以动态地延迟加载一个组件到一个容器:

const myFirstLazyComponent = await this.lazyComponentService.loadComponent(myFirstLazyModuleId, containerRef);

最新更新