- Компонент без модуля
Если мы хотим динамически (без модуля) динамически загружать компонент, то мы можем использовать тот же шаблон, что и с маршрутами:
// <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);
Модули
Если компонент зависит от других служб / компонентов, нам нужно загрузить модуль, для этого нам нужно указать angular для его компиляции. Это все еще проще, чем предыдущие приемы, использованные в предыдущих версиях Angular. Вот решение.
Мы можем создать сервис, который будет хранить ленивые ссылки на модули и динамически лениво загружать модуль (с учетом идентификатора модуля и ссылки на контейнер).
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;
}
}
Модули то, что должно быть загружено с отложенной загрузкой, тогда необходимо вызвать метод resolComponentFactory, это означает добавление службы к модулю следующим образом:
@NgModule({
imports: [
MyModules...
],
declarations: [
MyFirstLazyComponent
]
})
export class MyFirstLazyComponentModule {
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
public resolveComponent(): ComponentFactory<MyFirstLazyComponent> {
return this.componentFactoryResolver.resolveComponentFactory(MyFirstLazyComponent);
}
}
И тогда волхвы c работают, вы можете динамически лениво загрузить компонент к контейнеру:
const myFirstLazyComponent = await this.lazyComponentService.loadComponent(myFirstLazyModuleId, containerRef);