Angular递归树形组件选中样式异常问题求助
Angular递归树形视图选中样式跨子树失效问题修复
问题原因
当前每个递归的<app-tree>组件实例都独立维护自己的selectedItem状态,跨子树选择节点时,旧子树组件的selectedItem不会被更新,导致旧节点仍保留.node-active样式,新子树的节点样式正常,但旧节点的样式无法清除。
修复方案
将选中状态统一提升到根组件管理,所有树形组件通过@Input接收全局选中的节点code,点击节点时向上触发事件通知根组件更新选中状态,确保所有组件实例共用同一个选中值,实现跨子树的样式正确切换。
修改后的代码:
1. tree.component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ selector: 'app-tree', templateUrl: './tree.component.html', styleUrls: ['./tree.component.css'], }) export class TreeComponent { @Input() tree: any; @Input() selectedCode: string; // 接收全局选中的节点code @Output() nodeSelected = new EventEmitter<string>(); // 触发选中事件 @Output() selectedValue = new EventEmitter<any>(); toggleChild(node) { this.selectedValue.emit(node); node.showChildren = !node.showChildren; node.isOpen = !node.isOpen; } emitOnChildClicked(node) { this.selectedValue.emit(node); } applyStyle(node) { this.nodeSelected.emit(node.code); // 向上传递选中的节点code } }
2. tree.component.html
<ul *ngIf="tree" class="tree"> <li *ngFor="let node of tree; let i = index"> <div class="label-container" (click)="toggleChild(node)"> <span *ngIf="node.children != 0"> <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Icons8_flat_document.svg/512px-Icons8_flat_document.svg.png" class="arrow-btn" [ngClass]="node.isOpen ? 'open-btn' : 'close-btn'" /> </span> <span class="node-item" (click)="applyStyle(node)" [ngClass]="{ 'node-active': selectedCode == node.code }" > {{ node.name }} </span> </div> <app-tree *ngIf="node.showChildren" (selectedValue)="emitOnChildClicked($event)" (nodeSelected)="nodeSelected.emit($event)" [tree]="node.children" [selectedCode]="selectedCode" ></app-tree> </li> </ul>
3. 根组件(app.component.ts)
import { Component } from '@angular/core'; import { NODES } from './tree/tree.mock'; @Component({ selector: 'app-root', template: ` <app-tree [tree]="nodes" [selectedCode]="currentSelectedCode" (nodeSelected)="handleNodeSelected($event)" ></app-tree> `, }) export class AppComponent { nodes = NODES; currentSelectedCode: string; handleNodeSelected(code: string) { this.currentSelectedCode = code; } }
说明
- 根组件维护唯一的
currentSelectedCode,所有树形组件共享这个值,确保选中状态全局一致。 - 子组件点击节点时,通过
nodeSelected事件把选中的code传递给根组件,由根组件统一更新选中状态。 - 递归的子组件也会接收
selectedCode并传递选中事件,保证整个树形结构的状态同步。
内容的提问来源于stack exchange,提问作者blume0F
相关产品推荐
相关产品推荐

