Angular 6/7 AOT : Dynamic template render - load JitCompiler for module

标签 angular dynamic jit aot

我在根据 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 构建时未加载运行时编译器

我还尝试在 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

编辑 2019 年 1 月 15 日 下面是一个在 stackblitz.com 上运行的 JIT 示例,其中包含插值和数据绑定(bind)测试: https://stackblitz.com/github/lyczos/angular-dynamic-html-renderer

编辑 05.01.2020 目前,我已经开始使用 builder.io 史蒂夫(这个项目的作者)正在使用网络组件来让它工作。

最佳答案

首先,我很抱歉把这个写成一个答案,但它太长了,不适合作为评论。

可以按照您的要求进行操作。事实上,我今年在 ng-conf 上确实提出了这个问题。在 Max Koretskyi(又名 angularindepth.com 的“ng-wizard”作者)关于这个主题的一次 session 之后,我与他进行了交谈。

我必须警告你,虽然他提供的解决方案非常复杂、hacky,你不能指望它在未来的 Angular 版本中不会中断,因为你试图完成的事情违背了 Angular 框架,而这正是Angular 团队正试图阻止人们这样做。真的,尝试维护它只会是一场噩梦,任何新的开发人员都可能会竭尽全力试图理解我所做的事情。哎呀,如果我在一年多之后回顾它,我什至可能都不知道自己做了什么。

最终,我决定放弃 AOT 并使用 JIT 部署我的应用程序,此后我没有后悔我的决定。如果你决定你真的想进一步追求这个,我建议联系 Max。从我在 ng-conf 收集到的信息来看,他是一个非常友好的人,他公开邀请人们在有问题时与他联系。希望对您有所帮助,祝您好运! :)

关于 Angular 6/7 AOT : Dynamic template render - load JitCompiler for module,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53869438/

相关文章:

c# - 将具体对象类型作为泛型方法的参数传递

c# - 如果声明的类型是动态对象,则声明的属性不会被序列化

javascript - 我找到了如何在 typescript 中制作表格,但我不知道如何将其插入到html代码中

Angular,如何在延迟加载的模块中包含多个组件?

angular - on() 函数创建 Reducer 时出错

Angular4 显示来自服务器的图像

javascript - 旧输入数组和动态字段 - Laravel - Blade

java - 如何在低(汇编)级别捕获和处理异常?

Java System.nanoTime 经过的平均时间不断变小

C# - 真的需要 "volatile"作为关键字吗?