#angular #angular-ivy
#angular #angular-ivy
Вопрос:
Я пытаюсь лениво загрузить компонент в Angular Ivy
import("./app/products/products.module").then((module) => {
console.log(module.ProductsModule.ngInjectorDef.providers);
});
Код модуля
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { LazyComponent } from "./lazy/lazy.component";
@NgModule({
declarations : [LazyComponent],
imports : [
CommonModule
],
entryComponents: [
LazyComponent
],
providers : [
{
provide : "components",
useValue: {
lazy: LazyComponent,
}
}
]
})
export class ProductsModule {
}
Я смог получить доступ к поставщикам с помощью module.ProductsModule.ngInjectorDef.providers
, но я ищу лучший метод
Может быть, что-то вроде module.ProductsModule.ngInjectorDef.get("components")
Ответ №1:
У Ivy есть вызываемая частная функция createInjector
, она доступна с помощью theta в текущем API, но будет доступна позже, когда Ivy станет стабильным.
Предположим, у вас есть такой код:
@NgModule({
declarations: [LazyComponent],
providers: [
{
provide: 'components',
useValue: {
lazy: LazyComponent
}
}
],
entryComponents: [LazyComponent]
})
export class LazyModule {
static getLazyComponents: () => { lazy: typeof LazyComponent };
constructor(injector: Injector) {
LazyModule.getLazyComponents = () => injector.get('components');
}
}
Давайте отложим загрузку с LazyModule
помощью динамического импорта:
import { ɵcreateInjector as createInjector, Injector } from '@angular/core';
export class AppComponent {
constructor(injector: Injector) {
import('./lazy/lazy.module').then(({ LazyModule }) => {
createInjector(LazyModule, injector);
console.log(LazyModule.getLazyComponents());
});
}
}
Но, используя этот подход, вы откладываете загрузку модуля. Если вы хотите отложить загрузку компонента — вы можете сделать это без использования module, предположим LazyComponent
, что это находится внутри lazy.component.ts
file:
@Component({
selector: 'app-lazy',
template: `
<h1>I am lazy</h1>
`
})
export class LazyComponent {}
Вы можете использовать динамический импорт для загрузки этого компонента renderComponent
функции:
import { ɵrenderComponent as renderComponent, Injector } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<app-lazy></app-lazy>
`
})
export class AppComponent {
constructor(injector: Injector) {
import('./lazy.component').then(({ LazyComponent }) => {
renderComponent(LazyComponent, {
injector,
host: 'app-lazy'
});
});
}
}
Одно замечание — у ленивых компонентов НЕТ жизненного цикла! constructor
будут вызваны, но не такие перехваты ngOnInit
, как и т.д. ngOnDestroy
Возвращаясь к вашему вопросу о ленивом модуле — вы, вероятно, захотите предоставить фабрики компонентов этих ленивых компонентов, что-то вроде этого:
export class LazyModule {
static getComponentFactories: () => {
lazy: ComponentFactory<LazyComponent>;
};
constructor(resolver: ComponentFactoryResolver) {
LazyModule.getComponentFactories = () => ({
lazy: resolver.resolveComponentFactory(LazyComponent)
});
}
}
Если вы не хотите использовать статические функции, вы можете объявить методы экземпляра:
export class LazyModule {
constructor(private resolver: ComponentFactoryResolver) {}
public getComponentFactories() {
return {
lazy: this.resolver.resolveComponentFactory(LazyComponent)
};
}
}
А затем получите экземпляр этого модуля:
export class AppComponent {
constructor(private injector: Injector) {
import('./lazy/lazy.module').then(({ LazyModule }) => {
const injector = createInjector(LazyModule, this.injector);
const lazyModule = injector.get(LazyModule);
console.log(lazyModule.getComponentFactories());
});
}
}
Комментарии:
1. Спасибо, я бы
ɵcreateInjector
и через сто лет не разобрался : D2. @UnLoCo ха-ха: D да, я советую вам просто изучить API Ivy, скопировав этот символ theta и просто
ctrl f
: D как я это делал: D