You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 18:40:22