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

Angular列表项的选择、展开与折叠实现方案咨询

解决方案

核心功能实现思路

  • 用状态对象分别管理每个列表项的展开/折叠、选中状态,避免单个变量只能控制一项的局限性
  • 修正ViewChildren的使用方式,正确获取容器用于动态组件创建
  • 规范HTML结构(ul下直接放li,避免无效嵌套)

调整后的代码

HTML模板

<ul>
  <li *ngFor="let hero of heroArray; let i = index"
      (click)="toggleItem(i)"
      [class.selected]="selectedStates[i]">
    Topic {{i}}
    <!-- 用ngIf替代hidden,更符合Angular性能优化逻辑 -->
    <ng-container *ngIf="expandedStates[i]">
      <!-- 用于动态创建组件的容器模板 -->
      <ng-template #contentContainer></ng-template>
      <!-- 若无需动态创建,直接保留静态组件:<app-topiccontent></app-topiccontent> -->
    </ng-container>
  </li>
</ul>

TypeScript代码

import { Component, ViewChildren, QueryList, ViewContainerRef, AfterViewInit } from '@angular/core';
import { InmemorydataService } from '../inmemorydata.service';
import { TopiccontentComponent } from '../topiccontent/topiccontent.component';

@Component({
  selector: 'app-topicsmenu',
  templateUrl: './topicsmenu.component.html',
  styleUrls: ['./topicsmenu.component.scss'],
})
export class TopicsmenuComponent implements AfterViewInit {
  heroArray: any[] = [];
  // 存储每个项的展开状态,默认全部折叠
  expandedStates: {[key: number]: boolean} = {};
  // 存储每个项的选中状态,默认全部未选中
  selectedStates: {[key: number]: boolean} = {};

  // 获取所有内容容器的模板引用
  @ViewChildren('contentContainer') contentContainers!: QueryList<ViewContainerRef>;

  constructor(
    private dataService: InmemorydataService,
    private viewContainerRef: ViewContainerRef
  ) {}  

  ngOnInit() {
    this.dataService.createDb().subscribe(hero => {
      this.heroArray = hero;
      // 初始化所有项的状态
      hero.forEach((_, index) => {
        this.expandedStates[index] = false;
        this.selectedStates[index] = false;
      });
    });
  }

  ngAfterViewInit() {
    // 视图初始化完成后可操作ViewContainerRef
  }

  // 切换选中状态 + 展开/折叠状态
  toggleItem(index: number) {
    this.selectedStates[index] = !this.selectedStates[index];
    this.expandedStates[index] = !this.expandedStates[index];

    // 展开时创建组件,折叠时销毁组件
    if (this.expandedStates[index]) {
      this.createTopicContent(index);
    } else {
      this.contentContainers.get(index)?.clear();
    }
  }

  // 动态创建TopiccontentComponent
  createTopicContent(index: number) {
    const container = this.contentContainers.get(index);
    if (container) {
      container.clear(); // 清空容器避免重复创建
      const componentRef = container.createComponent(TopiccontentComponent);
      // 若需给组件传值,可通过componentRef.instance操作
      // componentRef.instance.heroData = this.heroArray[index];
    }
  }
}

可选样式补充(topicsmenu.component.scss)

li.selected {
  background-color: #f0f0f0;
  font-weight: 600;
}

关键问题修正说明

  1. 状态管理优化:替换单个Expanded变量为状态对象,实现每个列表项的独立状态控制
  2. ViewChildren修正:之前绑定的是ul元素,现在绑定到每个li内的容器模板,才能精准获取每个项的组件容器
  3. HTML结构规范:移除ul内的div嵌套,符合HTML语义化要求
  4. 动态组件生命周期:展开时创建组件,折叠时销毁组件,避免不必要的内存占用

内容的提问来源于stack exchange,提问作者azam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 12:43:23