【发布时间】:2019-05-21 00:29:02
【问题描述】:
我在从 API 响应“即时”构建模板时遇到问题,但仅限于 AoT 构建。
我从后端收到这样的回复:
<h1>Title...</h1>
<some-component></some-componen>
<p>other content</p>
我想像普通的 Angular 模板一样解析它。
我的组件的简化代码如下所示:
import {
Compiler,
Component,
ComponentFactory,
ComponentRef,
Injector,
Input,
NgModule,
OnChanges,
OnDestroy,
OnInit,
ViewContainerRef
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
export async function createComponentFactory(compiler: Compiler, metadata: Component): Promise> {
const cmpClass = class DynamicComponent {
};
const decoratedCmp = Component(metadata)(cmpClass);
// IMPORT ALL MODULES HERE!!!
@NgModule({imports: [CommonModule, RouterModule], declarations: [decoratedCmp]})
class DynamicHtmlModule {
}
const moduleWithComponentFactory = await compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule);
return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
}
@Component({
selector: 'html-renderer',
templateUrl: './html-renderer.component.html',
styleUrls: ['./html-renderer.component.scss']
})
export class HtmlRendererComponent implements OnInit, OnChanges, OnDestroy {
@Input() content: string;
cmpRef: ComponentRef;
constructor(private vcRef: ViewContainerRef, private compiler: Compiler) { }
ngOnInit(): void {
console.log('init...')
console.log(this.compiler)
}
ngOnDestroy() {
if (this.cmpRef) {
this.cmpRef.destroy();
}
}
ngOnChanges() {
const html = this.content;
if (!html) { return; }
if (this.cmpRef) {
this.cmpRef.destroy();
}
const compMetadata = new Component({
selector: 'dynamic-selector',
template: this.content,
});
createComponentFactory(this.compiler, compMetadata)
.then(factory => {
const injector = Injector.create({providers: [], parent: this.vcRef.injector});
this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
});
}
}
所以,我将整个数据传入content 输入,然后通过compileModuleAndAllComponentsAsync 方法(https://angular.io/api/core/Compiler#compilemoduleandallcomponentssync)编译所有组件
并且所有工作都在 JIT 构建中运行。
我想在 AoT 编译中完成这项工作,因为现在我收到一个错误:
Runtime Compiler is not loaded 在示例代码上使用 AoT 构建时
我也尝试在providers[] 的 app.module.ts 中提供编译器,但它也不起作用:
export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}
{provide: COMPILER_OPTIONS, useValue: {}, multi: true},
{provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS]},
{provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory]},
我的问题:有没有办法将延迟加载的模块包含在 JIT 编译器中以访问其方法?
我找到了一些相关的问题,但没有答案:
Error while using @angular compiler in Angular 5 and AOT-Build
编辑 15.01.2019 这是 stackblitz.com 上的一个有效 JIT 示例,其中包含插值和数据绑定测试: https://stackblitz.com/github/lyczos/angular-dynamic-html-renderer
编辑 05.01.2020 目前,我已经开始使用builder.io Steve(该项目的作者)正在使用 Web 组件来使其工作。
【问题讨论】:
-
其实我觉得这是个好问题。对我来说看起来不错! :)
-
让我改述一下:您想在不加载编译器的情况下使用编译器。很抱歉,这里有一个逻辑问题……您要么使用 JIT(带编译器)或 AOT(不带编译器)。 @Hatef 这怎么可能是个好问题?
-
@smnbbrv 对,但是有什么方法可以将编译器(即时)附加到延迟加载的模块上,以免增加初始应用程序加载时间?例如我在这里看到了这个,但它不适用于 Angular 6/7 github.com/alexzuza/angular2-build-examples/tree/master/…
-
@smnbbrv 好的,知道了。您是否看到任何其他可能的解决方案/想法来“即时”构建模板?
-
@smnbbrv 它的格式很好,包含了经过尝试的代码,添加了相关问题的链接,绝对是关于主题的,他们的问题很明确 - 如果 OP 的逻辑/他们试图做的事情没有对您/我们来说没有意义,这并不是一个坏问题。