Angular组件如何根据ng-content内容是否非空渲染不同模板
实现Angular独立组件的
hasNonEmptyTextContent方法 核心思路
通过@ContentChild获取投影内容的DOM元素引用,在内容初始化完成后提取并处理文本内容,判断是否包含非空白字符。同时使用ng-container和ng-template避免生成多余DOM节点。
组件类实现
import { Component, ContentChild, ElementRef, AfterContentInit, ChangeDetectorRef, AfterContentChecked } from '@angular/core'; @Component({ selector: 'app-custom-component', standalone: true, template: ` <ng-container *ngIf="hasNonEmptyText; else defaultContent"> <div class="formatted-wrapper"> <ng-content #projectedContent></ng-content> </div> </ng-container> <ng-template #defaultContent> <span class="default-text">默认文本</span> </ng-template> `, styles: [` .formatted-wrapper { padding: 8px; border: 1px solid #ccc; border-radius: 4px; } .default-text { color: #999; } `] }) export class CustomComponent implements AfterContentInit, AfterContentChecked { @ContentChild('projectedContent', { read: ElementRef }) projectedContent!: ElementRef<HTMLElement>; hasNonEmptyText = false; constructor(private cdr: ChangeDetectorRef) {} ngAfterContentInit(): void { this.hasNonEmptyText = this.hasNonEmptyTextContent(); } // 处理动态变化的投影内容(可选) ngAfterContentChecked(): void { const currentState = this.hasNonEmptyTextContent(); if (currentState !== this.hasNonEmptyText) { this.hasNonEmptyText = currentState; this.cdr.detectChanges(); } } private hasNonEmptyTextContent(): boolean { if (!this.projectedContent?.nativeElement) return false; // 提取文本并去除所有首尾空白字符 const rawText = this.projectedContent.nativeElement.textContent ?? ''; // 判断处理后的文本是否非空 return rawText.trim().length > 0; } }
关键细节说明
- 获取投影内容:给
ng-content添加模板变量#projectedContent,通过@ContentChild获取其ElementRef,确保能直接访问投影内容的DOM节点。 - 文本判断逻辑:
- 使用
textContent获取投影内容的所有文本(包括子元素的文本) - 调用
trim()去除首尾的空格、换行、制表符等空白字符 - 通过判断处理后的文本长度是否大于0,确定是否为非空内容
- 使用
- 避免多余DOM:使用
ng-container和ng-template作为条件渲染的容器,不会在DOM中生成额外的节点。 - 动态内容处理:如果投影内容是动态变化的(比如绑定的异步数据),实现
AfterContentChecked钩子,实时更新状态并触发变更检测。
使用示例
<!-- 场景1:包含非空文本 --> <app-custom-component> 这是需要格式化展示的内容 </app-custom-component> <!-- 场景2:仅包含空白字符(空格、换行等) --> <app-custom-component> </app-custom-component> <!-- 场景3:完全空的投影内容 --> <app-custom-component></app-custom-component>
注意事项
- 如果投影内容包含Angular组件,
textContent会获取该组件渲染后的文本内容,符合需求逻辑。 - 若需要排除特定元素的文本(比如某些装饰性元素),可以在
hasNonEmptyTextContent方法中进一步过滤DOM节点,例如通过querySelector排除特定类名的元素后再提取文本。
内容的提问来源于stack exchange,提问作者Gilmor
相关产品推荐
相关产品推荐

