Jas*_*son 3 typescript angular
我有一个仪表板应用程序,在这里我懒惰地加载小部件(与路线无关)。
我通过定义一个对象来做到这一点{name: string, loadChildren: string}。然后app.module我会做的provideRoutes(...)。
这将导致cli为每个小部件模块创建一个块。
然后在运行时,我将使用SystemJsModuleLoader加载该字符串并获取一个NgModuleRef。
使用,我可以创建一个从模块和调用组件createComponent上ViewContainerRef。
这是该函数:
loadWidget(
name: string,
container: ViewContainerRef,
widget: Widget
): Promise<{ instance: WidgetComponent; personlize?: { comp: any; factory: ComponentFactoryResolver } }> {
if (this.lazyWidgets.hasOwnProperty(name)) {
return this.loader.load(this.lazyWidgets[name]).then((moduleFactory: NgModuleFactory<any>) => {
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.injector);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
const comp = container.createComponent(compFactory);
(<WidgetComponent>comp.instance).widget = widget;
const personalize = (<any>moduleFactory.moduleType).personalize;
if (personalize) {
return {
instance: <WidgetComponent>comp.instance,
personlize: {
comp: personalize,
factory: moduleRef.componentFactoryResolver,
injector: moduleRef.injector
}
};
} else {
return {
instance: <WidgetComponent>comp.instance
};
}
});
} else {
return new Promise(resolve => {
resolve();
});
}
Run Code Online (Sandbox Code Playgroud)
在角度8中,loadChildren更改了导入功能。
取而代之的是NgModuleRef实际的模块实例。
我以为我可以通过采用该模块来对其代码进行修复,对其进行编译,以NgModuleRef使其余代码保持不变。
似乎在AOT模式下,尽管编译器未捆绑在一起。
因此,我现在基本上只能使用所需的组件实例,但是无法将其添加到View容器中。
它需要一个我无法获得的组件工厂解析器。
我想我的问题是如何获取一个组件实例并将其添加到角度8的视图容器中。目前,我已经恢复使用字符串字符串的childChild,但这只能在版本9发布之前起作用。
这是带有在AOT中不起作用的编译器的版本
if (this.lazyWidgets.hasOwnProperty(name)) {
return this.lazyWidgets[name]().then((mod: any) => {
const moduleFactory = this.compiler.compileModuleSync(mod);
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.injector);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
const comp = container.createComponent(compFactory);
(<WidgetComponent>comp.instance).widget = widget;
const personalize = (<any>moduleFactory.moduleType).personalize;
if (personalize) {
return {
instance: <WidgetComponent>comp.instance,
personlize: {
comp: personalize,
factory: moduleRef.componentFactoryResolver,
injector: moduleRef.injector
}
};
}
Run Code Online (Sandbox Code Playgroud)
这是一个我如何考虑但却无法将它添加到的例子ViewContainerRef。
模块实例实现了一个需要“ entry”属性的接口。
这定义了要加载的实际组件:
if (this.lazyWidgets.hasOwnProperty(name)) {
return this.lazyWidgets[name]().then((mod: any) => {
const comp = mod.entry;
(<WidgetComponent>comp.instance).widget = widget;
const personalize = mod.personalize;
if (personalize) {
return {
instance: <WidgetComponent>comp.instance,
personlize: {
comp: personalize,
factory: null //this no longer works: moduleRef.componentFactoryResolver,
// injector: moduleRef.injector
}
};
} else {
return {
instance: <WidgetComponent>comp.instance
};
}
});
}
Run Code Online (Sandbox Code Playgroud)
编辑:
我试图在stackblitz中添加一个示例,但是编译器将我的字符串转换为函数。至少代码更具可读性。这是我在angular 8中所做的。我基本上需要一种方法来import()代替魔术弦。
在角8的结果loadChildren函数要么是Promise的NgModule在JIT模式或类型Promise的NgModuleFactory在AOT模式。
考虑到这一点,您可以按以下方式重写服务:
import {
Injectable, Compiler, Injector, Type,
ViewContainerRef, ComponentFactoryResolver,
NgModuleFactory, Inject
} from '@angular/core';
@Injectable()
export class LazyLoaderService {
constructor(private injector: Injector,
private compiler: Compiler,
@Inject(LAZY_WIDGETS) private lazyWidgets:
{ [key: string]: () => Promise<NgModuleFactory<any> | Type<any>> }) { }
async load(name: string, container: ViewContainerRef) {
const ngModuleOrNgModuleFactory = await this.lazyWidgets[name]();
let moduleFactory;
if (ngModuleOrNgModuleFactory instanceof NgModuleFactory) {
// aot mode
moduleFactory = ngModuleOrNgModuleFactory;
} else {
// jit mode
moduleFactory = await this.compiler.compileModuleAsync(ngModuleOrNgModuleFactory);
}
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.injector);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
const comp = container.createComponent(compFactory);
}
}
Run Code Online (Sandbox Code Playgroud)
提示:如有疑问,请始终查看源代码
| 归档时间: |
|
| 查看次数: |
1727 次 |
| 最近记录: |