如何通过@ViewChild动态实例化带模板引用变量的模板?
解决Angular中@ViewChild获取模板配合*ngTemplateOutlet的变更检测错误
你遇到的ExpressionChangedAfterItHasBeenCheckedError是Angular变更检测机制的典型问题,核心原因如下:
- 组件初始化时,
@ViewChild("mytemplate")标记的template变量初始值为undefined - Angular第一次变更检测时,
*ngTemplateOutlet="template"使用的就是这个undefined值 - 而Angular会在第一次变更检测完成后,才完成
@ViewChild对模板引用的赋值,此时template变成了TemplateRef对象 - 这种变更检测前后值不一致的情况,直接触发了错误
最简解决方法:给@ViewChild添加static选项
修改组件类中的@ViewChild装饰器,添加{ static: true }配置,让Angular在组件初始化阶段就获取到模板引用,避免后续值变化导致的检测冲突:
import { Component, TemplateRef, ViewChild } from '@angular/core'; @Component({ selector: 'app-root', template: ` <ng-template #mytemplate> <p>Hello World</p> </ng-template> <ng-container *ngTemplateOutlet="template"></ng-container> ` }) export class AppComponent { @ViewChild("mytemplate", { static: true }) template!: TemplateRef<any>; }
其他可选方案
直接使用模板引用变量(推荐)
既然你已经知道可以直接把mytemplate传给*ngTemplateOutlet,这其实是最简洁且能避免变更检测问题的方式:<ng-template #mytemplate> <p>Hello World</p> </ng-template> <ng-container *ngTemplateOutlet="mytemplate"></ng-container>手动触发变更检测
如果必须在视图初始化后获取模板(比如模板处于条件渲染逻辑中),可以在ngAfterViewInit生命周期钩子中手动触发变更检测:import { Component, TemplateRef, ViewChild, ChangeDetectorRef, AfterViewInit } from '@angular/core'; @Component({ selector: 'app-root', template: ` <ng-template #mytemplate> <p>Hello World</p> </ng-template> <ng-container *ngTemplateOutlet="template"></ng-container> ` }) export class AppComponent implements AfterViewInit { @ViewChild("mytemplate") template!: TemplateRef<any>; constructor(private cdr: ChangeDetectorRef) {} ngAfterViewInit() { this.cdr.detectChanges(); } }
内容的提问来源于stack exchange,提问作者Display Name
相关产品推荐
相关产品推荐

