如何在Angular的*ngFor循环中动态生成多个差异化组件?
当然可以!而且这绝对是比堆一堆*ngIf更优雅、更易维护的方案——毕竟组件数量还在增加,总不能一直手动加模板标签对吧?不过你直接写{{item.component}}是行不通的,Angular没办法直接把组件类当成字符串渲染出来,得用专门的动态组件加载方式,这里最适合的就是ngComponentOutlet指令,我给你一步步讲怎么实现:
第一步:定义你的组件列表
先在组件类里维护一个包含标题和对应组件类的数组,这样新增组件只需要往数组里加项就行:
import { Component1, Component2, Component3 } from './your-components-path'; @Component({ selector: 'app-tab-wrapper', templateUrl: './tab-wrapper.component.html' }) export class TabWrapperComponent { activeTab = 0; // 默认激活第一个tab tabList = [ { title: 'Component 1', component: Component1 }, { title: 'Component 2', component: Component2 }, { title: 'Component 3', component: Component3 }, // 以后加新组件直接在这加就行 ]; }
第二步:用ngComponentOutlet动态渲染组件
在模板里,你可以先渲染tab切换的头部,然后根据当前激活的tab,动态渲染对应的组件:
<!-- Tab 切换头部 --> <div class="tab-nav"> <button *ngFor="let tab of tabList; let i = index" (click)="activeTab = i" [class.active]="i === activeTab" > {{ tab.title }} </button> </div> <!-- 动态渲染当前激活的组件 --> <ng-container *ngComponentOutlet="tabList[activeTab].component"></ng-container>
进阶:给动态组件传参/监听事件
如果你的组件需要接收输入参数或者向外发射事件,ngComponentOutlet也支持:
<ng-container *ngComponentOutlet=" tabList[activeTab].component; inputs: { itemData: currentTabData }; <!-- 传递@Input()参数 --> outputs: { itemClicked: handleTabEvent($event) } <!-- 监听@Output()事件 --> " ></ng-container>
对应的组件类里要处理这些:
// 比如Component1的代码 @Component({...}) export class Component1 { @Input() itemData: any; @Output() itemClicked = new EventEmitter<any>(); // ...组件逻辑 }
懒加载组件优化(可选)
如果你的组件体积比较大,还可以用懒加载来优化首屏性能,只在切换到对应tab时才加载组件:
tabList = [ { title: 'Component 1', // 动态导入组件,返回Promise component: () => import('./component1.component').then(m => m.Component1) }, // 其他组件同理 ];
模板里需要配合async管道:
<ng-container *ngComponentOutlet="tabList[activeTab].component() | async" ></ng-container>
注意事项
- Angular 9+ 不需要再在模块的
entryComponents里声明动态组件了,只要组件是正常声明在模块里(或者是Angular 14+的独立组件),Angular会自动处理。 - 如果你的组件依赖其他服务,确保这些服务已经在模块或组件的
providers里配置好,动态组件会继承父组件的注入器。
这样一改,以后新增组件只需要在tabList里加一行,模板完全不用动,完美解决你组件数量增长的维护问题!
内容的提问来源于stack exchange,提问作者Sergey
相关产品推荐
相关产品推荐

