Angular中是否有类似React的简洁组件条件显示实现方案?
这种紧凑条件渲染方案在Angular中完全可实现,优先选择结构型指令方案,性能和原生*ngIf完全一致,且不会生成任何额外外层DOM节点,完全符合你的需求。
最优实现方案
方案1:结构型指令实现(更推荐)
结构型指令是Angular原生提供的操作DOM视图的能力,没有多余宿主节点,性能最优,兼容所有Angular版本。
- 指令代码:
import { Directive, Input, TemplateRef, ViewContainerRef, OnChanges } from '@angular/core'; @Directive({ selector: '[ifElse]', standalone: true // Angular 14以下版本删除该行,将指令加入对应NgModule的declarations数组 }) export class IfElseDirective implements OnChanges { @Input('ifElse') condition: boolean | null | undefined = false; @Input() ifElseThen!: TemplateRef<unknown>; @Input() ifElseElse!: TemplateRef<unknown>; constructor(private viewContainerRef: ViewContainerRef) {} ngOnChanges(): void { this.viewContainerRef.clear(); const template = this.condition ? this.ifElseThen : this.ifElseElse; if (template) { this.viewContainerRef.createEmbeddedView(template); } } }
- 模板使用(利用Angular微语法,写法更紧凑):
<ng-container *ifElse="loggedIn; then avatarTpl; else signInTpl"></ng-container> <ng-template #avatarTpl> <avatar></avatar> </ng-template> <ng-template #signInTpl> <sign-in-button></sign-in-button> </ng-template>
方案2:组件式实现(更贴近你举例的写法)
如果更偏好你举例的包裹式写法,可以用组件实现,配合display: contents消除外层宿主节点的布局影响:
- 组件代码:
import { Component, Input, ContentChild, TemplateRef } from '@angular/core'; @Component({ selector: 'if-else', standalone: true, template: ` <ng-container *ngIf="condition; else elseBlock"> <ng-container *ngTemplateOutlet="ifTpl"></ng-container> </ng-container> <ng-template #elseBlock> <ng-container *ngTemplateOutlet="elseTpl"></ng-container> </ng-template> `, host: { 'style': 'display: contents' } }) export class IfElseComponent { @Input() condition!: boolean | null | undefined; @ContentChild('if') ifTpl!: TemplateRef<unknown>; @ContentChild('else') elseTpl!: TemplateRef<unknown>; }
- 模板使用:
<if-else [condition]="loggedIn"> <ng-template #if> <avatar></avatar> </ng-template> <ng-template #else> <sign-in-button></sign-in-button> </ng-template> </if-else>
注意:受Angular渲染机制限制,两个分支必须用ng-template包裹,不能直接给普通组件加#if/#else引用,因为普通元素的模板引用拿到的是组件实例而非渲染模板,无法实现动态条件渲染。
扩展能力
可以自行扩展上述实现,直接支持Observable类型的condition参数,自动做订阅和取消订阅处理,不用手动加async管道,进一步简化异步场景的写法。
内容的提问来源于stack exchange,提问作者Greg Van Gorp
相关产品推荐
相关产品推荐

