如何创建行为类似ng-container的Angular组件,渲染后DOM不保留宿主标签
需求完全可以实现,有两种成熟的实现方案
方案1:属性选择器方案(Angular官方推荐的无宿主组件实现方式)
你之前报错的原因是组件selector同时配置了元素选择器my-toolbar和属性选择器[my-toolbar],导致匹配冲突,按以下配置即可解决:
- 修改组件的selector为纯属性选择器,不要保留元素选择器:
// my-toolbar.component.ts @Component({ selector: '[myToolbar]', // 仅保留属性选择器 template: ` <ion-toolbar> <ng-content></ng-content> <!-- 内容投影插槽 --> </ion-toolbar> ` }) export class MyToolbarComponent {}
- 业务使用时直接给任意标签加属性即可,不会生成额外的
<my-toolbar>宿主标签:
<!-- 业务代码 --> <ng-container myToolbar> <span>stuff</span> </ng-container>
最终渲染的DOM结构和你的预期完全一致,不会出现多余的宿主标签。
方案2:手动移除宿主元素(保留<my-toolbar>元素选择器使用方式)
如果你不想修改业务端的使用习惯,要保留<my-toolbar>标签的写法,可以在组件初始化时用Angular提供的DOM操作API手动移除宿主:
// my-toolbar.component.ts import { Component, ElementRef, AfterViewInit, Renderer2 } from '@angular/core'; @Component({ selector: 'my-toolbar', template: ` <ion-toolbar> <ng-content></ng-content> </ion-toolbar> ` }) export class MyToolbarComponent implements AfterViewInit { constructor( private elementRef: ElementRef, private renderer: Renderer2 ) {} ngAfterViewInit() { const hostElement = this.elementRef.nativeElement; const parentElement = this.renderer.parentNode(hostElement); // 取出组件模板里的ion-toolbar元素 const toolbarElement = hostElement.firstElementChild; // 将ion-toolbar插入到宿主元素的同级位置 this.renderer.insertBefore(parentElement, toolbarElement, hostElement); // 移除多余的宿主元素 this.renderer.removeChild(parentElement, hostElement); } }
业务端无需修改代码,还是按照原来的写法使用即可:
<my-toolbar> <span>stuff</span> </my-toolbar>
最终渲染的DOM也不会出现<my-toolbar>标签,完全符合需求。
内容的提问来源于stack exchange,提问作者Harald
相关产品推荐
相关产品推荐

