免责声明:此问题是受Medium上“ Here is what you need to know about dynamic components in Angular”帖子的启发。
作者在那里展示了如何动态地生成模块和组件,将后者放入前者,动态地编译模块,获得组件工厂,并通过ViewContainerRef使用它来生成组件
这在基本设置中很好用。
现在让我们假设我们要动态生成一个组件,但是这次是使用使用async管道的模板。
下一步,我们需要在生产环境中使用此工具,这意味着两件事:
由于没有Angular编译器,因此我们可以在应用程序根模块中为jit compiler的Compiler令牌提供实例。
app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import {Compiler, NgModule} from '@angular/core';
import {AppComponent } from './app.component';
import {JitCompilerFactory} from '@angular/platform-browser-dynamic';
export function jitCompiler() {
/*
* Cast JitCompilerFactory to any because
* jit compiler factory constructor does not
* accept any arguments according to the @angular/platform-browser-dynamic/src/compiler_factory.d.ts
*/
const klass = (JitCompilerFactory as any);
return new klass([]).createCompiler([
{
useJit: true
}
]);
}
@NgModule({
declarations: [
AppComponent
],
providers: [
{
provide: Compiler,
useFactory: jitCompiler
}
],
imports: [
BrowserModule
],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
import {
AfterViewInit,
ChangeDetectionStrategy,
Compiler,
Component,
NgModule,
ViewContainerRef
} from '@angular/core';
import {Subject} from 'rxjs';
import {CommonModule} from '@angular/common';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements AfterViewInit {
constructor(
private readonly compiler: Compiler,
private readonly vcr: ViewContainerRef
) {}
ngAfterViewInit() {
const template = '<span>Hello, {{text$ }}</span>';
const cmp = Component({
template
})(class DynamicComponent {
text$: Subject<string>;
});
const module = NgModule({
declarations: [cmp],
imports: [CommonModule],
providers: []
})(class DynamicModule {});
this.compiler.compileModuleAndAllComponentsAsync(module)
.then(compiledModule => {
const dynamicComponent = this.vcr.createComponent(compiledModule.componentFactories[0]);
const sub = new Subject();
sub.next('World!');
dynamicComponent.instance.text$ = sub;
// Just to simulate some server updates
setTimeout(() => dynamicComponent.instance.text$.next('Another'), 3e3);
});
}
}
如果运行该代码并打开DevTools,则会看到以下错误:
错误错误:模块导入了意外的值'function(){}' '功能(){}'。请添加@NgModule批注。
仅在开发模式下会发生此问题。 Angular版本是7.2.0。
出现问题-要使其在AOT模式下工作必须做什么?