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

如何在Angular子组件的多个位置渲染同一份ng-content内容

问题根因

你遇到的问题本质是Angular中<ng-content>的单次投射特性:<ng-content>只会将传入的DOM节点移动到它第一次被渲染的位置,你将<ng-content>包裹在单个<ng-template>中多次调用*ngTemplateOutlet时,并不会生成新的DOM副本,只会将同一组DOM节点在不同渲染位置之间移动。当你打开mat-menu时,菜单内的模板被激活渲染,按钮节点就被移动到了菜单中,原组件区域的按钮自然就消失了。

修复方案

调整为「父组件传入模板引用、容器组件多次渲染模板」的方式即可实现多位置渲染,每次调用模板都会生成独立的DOM节点,不会出现节点被移动的问题:

1. 修改容器组件逻辑

首先在容器组件的ts文件中添加@ContentChild注解,接收父组件传入的模板:

import { Component, ContentChild, TemplateRef } from '@angular/core';

@Component({
  selector: 'container',
  templateUrl: './container.component.html',
  styleUrls: ['./container.component.css']
})
export class ContainerComponent {
  // 接收父组件传入的contentTpl模板
  @ContentChild('contentTpl') contentTpl!: TemplateRef<any>;
}

容器组件的模板保持原有渲染逻辑即可,无需修改:

<section id="buttons">
  <ng-container *ngTemplateOutlet="contentTpl"></ng-container>
</section>

<button mat-button [matMenuTriggerFor]="menu">Menu</button>
<mat-menu #menu="matMenu">
  <ng-container *ngTemplateOutlet="contentTpl"></ng-container> 
</mat-menu>

2. 调整父组件调用方式

将需要重复渲染的按钮内容包裹在ng-template标签中,标注模板引用#contentTpl即可:

<container>
  <ng-template #contentTpl>
    <button mat-raised-button (click)="foo()">foo</button>
    <button mat-raised-button (click)="bar()">bar</button>
  </ng-template>
</container>

该方案下两个位置渲染的按钮是完全独立的DOM节点,点击事件和样式都不会互相影响,打开菜单时原位置的按钮也不会消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 12:57:03