You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中是否有必要按需动态获取ng-template模板引用?

问题描述

我在Base组件中声明了一个summary模板,所属表单组件共包含4个标签页,仅当用户点击最后一个标签页时才会渲染该summary模板。请问是否有必要仅在用户点击最后一个标签页时才获取该summary模板的TemplateRef引用?这种实现方式有什么优势?

相关代码

Base组件代码

<!-- 模板部分 -->
<ng-template #appSummary let-summary>xx</ng-template>
// 类方法
getAppSummaryRef(): TemplateRef<any> {
  return this.appSummary ;
}

表单组件写法1(动态获取引用)

constructor(){
  this.lastTab$.pipe(distinctUntilChanged()).subscribe((summaryTab: any) => {
      this.summaryRef = !!summaryTab ? this.baseComp.getAppSummaryRef() : null;
    });
}

表单组件写法2(构造函数直接获取引用)

constructor(){
  this.summaryRef = this.baseComp.getAppSummaryRef();
}

回答

没有必要特意实现写法1的动态获取/置空逻辑,常规场景下写法2的直接获取方式就够用,甚至更稳妥。

首先要明确TemplateRef的本质:它是Angular编译模板阶段生成的、指向<ng-template>定义的轻量引用对象,本身不持有渲染后的组件/DOM实例,也不会触发模板内部的逻辑执行。只要Base组件完成初始化,这个引用就是固定存在的,提前拿到存储也不会产生任何额外性能开销。

很多人认为动态获取更省性能,本质是认知误区:

  • 从你贴的代码来看,#appSummary是直接声明在Base组件根模板下的,没有被*ngIf等结构性指令包裹,只要Base组件不销毁,对应的TemplateRef实例就会一直存在。你在表单组件切tab时把summaryRef设为null,根本不会触发这个对象的垃圾回收,完全是无效操作。
  • 模板内部的内容只有在实际通过*ngTemplateOutlet渲染、或者手动调用createEmbeddedView创建嵌入视图时才会被实例化。不管你多早拿到TemplateRef,只要不执行渲染操作,就不会生成DOM、不会执行模板内的绑定逻辑,完全不存在“提前加载”的额外开销。

反过来写法1还会平白增加问题风险:

  • 你需要额外维护一个订阅流,还要手动处理订阅的生命周期避免内存泄漏;
  • 一旦tab切换事件和模板渲染的时机没有对齐,很容易出现切到最后一个tab时summaryRef仍为null,导致summary区域渲染空白的异常。

只有一种场景需要用动态获取的逻辑:如果#appSummary模板本身被结构性指令包裹,比如它直接放在最后一个标签页的容器内部,未切到最后tab时这个ng-template本身都没有被初始化,构造函数阶段获取会拿到undefined,这时候才需要等模板存在后再获取引用。你当前的代码场景不满足这个前提,不需要多此一举。


内容的提问来源于stack exchange,提问作者Evan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 11:24:15