我在通过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编译中完成这项工作,因为现在出现错误:
在示例代码上使用AoT构建时,Runtime Compiler is not loaded
我还尝试在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
答案 0 :(得分:2)
首先,我很抱歉将其写为答案,但作为评论太久了。
可以按照您的要求进行操作。实际上,我今年确实在ng-conf上提出了这个确切的问题。在就此主题进行了一次会议之后,我与Max Koretskyi(又名angularindepth.com的“ ng-wizard”作者)进行了交谈。
我必须警告您,尽管他提供的解决方案非常复杂,棘手,并且您不能依靠它在将来的Angular版本中不会中断,因为您要实现的目标与Angular框架背道而驰Angular团队正试图阻止人们这样做。真的,要维护它只是一场噩梦,任何新的开发人员都可能会冒出顶峰,试图了解我所做的事情。哎呀,如果我一年后再回顾一下,我什至不知道我做了什么。
最终,我决定放弃AOT,并使用JIT部署了我的应用程序,此后我就不后悔自己的决定。如果您确定您真的想进一步追求这个目标,我建议您与Max取得联系。从我在ng-conf上收集的信息来看,他是一个非常友好的人,他公开邀请人们在遇到问题时与他联系。希望能有所帮助,祝您好运! :)
答案 1 :(得分:0)
去年我遇到了同样的问题,并且能够找到解决方法。我在样式指南中使用了动态生成的角度分量。这是一个适用于AOT编译的工作示例:
https://github.com/johncrim/angular-dynamic-styleguide
将import 'core-js/es7/reflect';
添加到polyfills.ts
是关键的非显而易见的技巧。
使用ng build --prod
运行动态编译的组件也需要
"buildOptimizer": false,
在angular.json的生产配置中。请注意,关闭buildOptimizer可能会增加包的大小,但是至少您会获得预编译大多数代码的好处。