Angular8中如何在TypeScript内解析含ngFor的模板并获取输出HTML
Angular 8 运行时解析动态模板(含Angular指令)的实现方案
Angular 2+ 默认采用AOT预编译模式,模板需在编译期提前确定,没有AngularJS中$interpolate的开箱实现。要实现运行时解析带指令、数据绑定的动态模板,可通过JIT编译器动态创建临时组件和模块的方式完成,具体实现如下:
完整实现步骤
1. 模板中添加动态渲染容器
在你的业务组件模板中添加用于挂载动态内容的容器:
<ng-container #dynamicTemplateContainer></ng-container>
2. 编写动态编译渲染逻辑
业务组件代码示例:
import { Component, Compiler, NgModule, ViewChild, ViewContainerRef, Injector } from '@angular/core'; import { CommonModule } from '@angular/common'; // 导入你的接口服务 import { YourDataService } from './your-data.service'; @Component({ selector: 'app-your-component', templateUrl: './your-component.component.html' }) export class YourComponent { reportData: any; // 获取容器引用 @ViewChild('dynamicTemplateContainer', { static: true }) dynamicContainer: ViewContainerRef; constructor( private compiler: Compiler, private injector: Injector, private service: YourDataService ) {} getDataFromAPI(){ this.reportData = { metaData: [ [ { 'label' : 'test1', 'value' : 'test2' } ], [ { 'label' : 'test3', 'value' : 'test4' } ] ] }; this.service.fetchData(params).subscribe((templateStr: string) => { // 拿到接口返回的模板后触发渲染 this.renderDynamicTemplate(templateStr, this.reportData); }); } private renderDynamicTemplate(template: string, context: any) { // 清空容器内之前的内容 this.dynamicContainer.clear(); // 动态创建临时组件,绑定传入的模板和数据上下文 @Component({ template: template }) class DynamicTemplateComponent { reportData = context; } // 动态创建临时模块,导入CommonModule保证内置指令(*ngFor、*ngIf等)可正常使用 @NgModule({ imports: [CommonModule], declarations: [DynamicTemplateComponent] }) class DynamicTemplateModule {} // JIT编译模块与组件 this.compiler.compileModuleAndAllComponentsAsync(DynamicTemplateModule) .then(factories => { // 匹配到动态组件的工厂 const componentFactory = factories.componentFactories.find( factory => factory.componentType === DynamicTemplateComponent ); // 创建组件实例并插入到容器 const componentRef = componentFactory.create(this.injector, [], null, this.dynamicContainer.injector); this.dynamicContainer.insert(componentRef.hostView); }); } }
注意事项
- 若项目生产环境默认开启AOT编译,需修改
angular.json对应项目的build配置:将aot改为false、buildOptimizer改为false,否则JIT编译器会被打包优化导致无法使用。 - 仅需解析
{{}}插值表达式、不需要处理Angular指令的场景,可以使用轻量的插值解析方法,无需引入JIT编译器,性能更高:
function interpolate(template: string, context: any): string { return template.replace(/{{\s*([\w.]+)\s*}}/g, (match, key) => { return key.split('.').reduce((data, k) => data?.[k], context) ?? match; }); }
- 动态加载不可信的外部模板存在XSS安全风险,请确保API返回的模板来源可信。
内容的提问来源于stack exchange,提问作者DEEPAK PRABHU
相关产品推荐
相关产品推荐

