Angular 16独立组件嵌套时无法渲染的问题排查
我创建了两个Angular 16独立组件,尝试将其中一个嵌套到另一个中使用。在浏览器开发者工具的Elements标签中,能看到该组件已被渲染到HTML中,甚至包含通过@Input传入的数据,但组件并未在页面上显示。
我的父组件SidebarComponent的装饰器如下:
@Component({ selector: 'sidebar', standalone: true, imports: [CommonModule, LinkComponent], templateUrl: './sidebar.component.html', styleUrls: ['./sidebar.component.css'] })
如你所见,我在imports数组中导入了LinkComponent,其装饰器如下:
@Component({ selector: 'link', standalone: true, imports: [CommonModule], templateUrl: './link.component.html', styleUrls: ['./link.component.css'] })
最初我在SidebarComponent的模板中这样使用LinkComponent:
<section class="linkContainer"> <link *ngFor="let link of Links" [Link]="link" /> </section>
如前所述,我能在Elements标签中看到每个link组件,但屏幕上没有任何显示。我尝试添加闭合标签改为<link></link>,但VSCode在我按下/键后会自动补全父级<section>标签。后来我在顶级元素外输入时,出现了以下错误:
Void elements do not have end tags "link"
我不知道是什么让我的组件成为Void元素,也不知道如何修改。除此之外我的代码其他部分都能正常运行,为了排查可能存在的其他问题,以下是我的完整代码:
SidebarComponent
@Component({ selector: 'sidebar', standalone: true, imports: [CommonModule, LinkComponent], templateUrl: './sidebar.component.html', styleUrls: ['./sidebar.component.css'] }) export class SidebarComponent implements OnInit{ Links!: Link[]; constructor(private linkService: SidebarService){ } ngOnInit(): void { this.loadLinks(); } private loadLinks(): void{ this.Links = this.linkService.getLinks(); console.log(this.Links); } }
SidebarComponent 模板
<nav class="mainContainer"> <svg class="closeButton" viewBox="0 0 20 20" width="20px" height="20px"> <use href="#close_button" fill="hsl(var(--gray-400))" /> </svg> <section class="linkContainer"> <link *ngFor="let link of Links" [Link]="link" /> </section> </nav>
SidebarService
export const LINKS: Link[] = [ { id: 'introduction', title: 'Introduction', path: 'home' }, { id: 'gettingStarted', title: 'Getting Started', path: 'getting-started' }, { id: 'libraries', title: 'Libraries', path: 'libraries', subLinks: [ { id: 'boxSize', title: 'Box Size Library', path: 'box-size-library' }, { id: 'textSize', title: 'Text Size Library', path: 'text-size-library' }, { id: 'lineSize', title: 'Line Size Library', path: 'line-size-library' } ] }, { id: 'classes', title: 'Classes', path: 'classes', subLinks: [ { id: 'srcryBox', title: 'Srcry Box Class', path: 'srcry-box-class' }, { id: 'srcryTxt', title: 'Srcry Text Class', path: 'srcry-text' } ] } ] @Injectable({ providedIn: 'root' }) export class SidebarService { Links : Link[] = []; constructor() { this.loadLinks(); } private loadLinks(): void{ this.Links = LINKS; } public getLinks(): Link[]{ return this.Links; } }
LinkComponent
@Component({ selector: 'link', standalone: true, imports: [CommonModule], templateUrl: './link.component.html', styleUrls: ['./link.component.css'] }) export class LinkComponent { @Input() Link!: Link; @Output() Selection: EventEmitter<string> = new EventEmitter<string>(); public updatePage(path: string): void{ this.Selection.emit(path); } }
LinkComponent 模板
<section> <article> <p>{{Link.title}}</p> </article> </section>
解决方案
问题出在你给LinkComponent设置的选择器是link——这是HTML原生的空元素(Void Element),比如<img>、<br>这类元素,浏览器规定它们不需要闭合标签,也不会渲染内部的任何内容。
所以即使Angular把组件的内容插入到<link>标签里,浏览器也会忽略这些内容,导致你看不到组件的显示。
修复步骤:
- 修改
LinkComponent的选择器,避免和HTML原生标签冲突,比如改成app-link或者sidebar-link:
@Component({ selector: 'app-link', // 此处修改选择器名称 standalone: true, imports: [CommonModule], templateUrl: './link.component.html', styleUrls: ['./link.component.css'] })
- 在
SidebarComponent的模板中,把使用组件的地方改成新的选择器:
<section class="linkContainer"> <app-link *ngFor="let link of Links" [Link]="link"></app-link> </section>
这样修改后,浏览器就会正常渲染你的组件内容,不会再把它当作原生空元素处理了。
内容的提问来源于stack exchange,提问作者Optiq
相关产品推荐
相关产品推荐

