【问题标题】:Angular Ivy: read module providersAngular Ivy:读取模块提供程序
【发布时间】:2019-07-24 23:43:01
【问题描述】:

我正在尝试在 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")

【问题讨论】:

    标签: angular angular-ivy


    【解决方案1】:

    Ivy 有一个名为createInjector 的私有函数,它在当前 API 中以 theta 形式公开,但稍后 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());
        });
      }
    }
    

    但是使用这种方法 - 你会延迟加载一个模块。如果你想延迟加载组件 - 你可以在不使用模块的情况下做到这一点,假设这个 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,但不会调用ngOnInitngOnDestroy 等钩子。

    回到你关于惰性模块的问题——你可能想要暴露那些惰性组件的组件工厂,像这样:

    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());
        });
      }
    }
    

    【讨论】:

    • 谢谢,一百年后我都想不通ɵcreateInjector:D
    • @UnLoCo haha​​ :D 是的,我建议你通过复制 theta 符号和 ctrl + f 来探索 Ivy 的 API :D 虽然我正在这样做:D
    猜你喜欢
    • 1970-01-01
    • 2018-03-10
    • 2017-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多