Angular Ivy: чтение поставщиков модулей

Я пытаюсь лениво загрузить компонент в Angular Ivy

import("./app/products/products.module").then((module) => {
  console.info(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")

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
0
769
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У Ivy есть частная функция под названием createInjector, она доступна с помощью тета в текущем 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.info(LazyModule.getLazyComponents());
    });
  }
}

Но при таком подходе вы лениво загружаете модуль. Если вы хотите лениво загрузить компонент - вы можете сделать это без использования модуля, предположим, что это LazyComponent, который находится внутри lazy.component.ts файла:

@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.info(lazyModule.getComponentFactories());
    });
  }
}

Спасибо, я бы и через сто лет не разобрался ɵcreateInjector :D

unloco 24.07.2019 18:44

@UnLoCo, ха-ха: D, да, я советую вам просто изучить API Айви, скопировав этот тета-символ и просто ctrl + f: D, хотя я делал это: D

overthesanity 24.07.2019 19:29

Другие вопросы по теме