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

如何在ngx-virtual-scroll中实现多个div的折叠/展开功能

Angular ngx-virtual-scroller 分组批量展开/折叠实现步骤
  • 第一步:调整数据结构,新增状态控制字段
    给分组和子项分别新增状态标记,用来控制全量/单个展开状态,参考类型定义如下:
// 子项类型定义
interface GroupChildItem {
  id: number;
  content: string;
  // 单个子项展开状态
  isExpanded: boolean;
}

// 分组类型定义
interface Group {
  groupTitle: string;
  // 分组下所有子项是否全展开
  isAllExpanded: boolean;
  children: GroupChildItem[];
}
  • 第二步:组件内实现状态切换逻辑
    在组件类中新增批量切换、单个切换的方法,同时适配虚拟滚动的高度更新逻辑:
import { VirtualScrollerComponent } from 'ngx-virtual-scroller';

@Component({
  // 你的组件配置
})
export class YourComponent {
  // 引入虚拟滚动组件实例
  @ViewChild(VirtualScrollerComponent) scroller!: VirtualScrollerComponent;

  groups: Group[] = []; // 你的分组数据源

  // 分组批量切换展开/折叠
  toggleGroupAll(group: Group): void {
    const targetState = !group.isAllExpanded;
    // 批量更新当前分组下所有子项的展开状态
    group.children.forEach(item => item.isExpanded = targetState);
    group.isAllExpanded = targetState;
    // 通知虚拟滚动重新计算容器高度,避免出现空白区域
    this.scroller.checkResize();
  }

  // 单个子项切换展开/折叠
  toggleSingleItem(item: GroupChildItem, group: Group): void {
    item.isExpanded = !item.isExpanded;
    // 单个切换后同步更新分组全展开状态:所有子项都展开时分组标记为全展开
    group.isAllExpanded = group.children.every(child => child.isExpanded);
    this.scroller.checkResize();
  }

  // 虚拟滚动trackBy优化,减少不必要的重渲染
  trackByGroup(index: number, group: Group): string {
    return group.groupTitle;
  }

  trackByChild(index: number, item: GroupChildItem): number {
    return item.id;
  }
}
  • 第三步:模板绑定状态与事件
    在模板中绑定状态和点击事件,实现UI和状态的同步:
<ngx-virtual-scroller 
  [items]="groups" 
  [trackBy]="trackByGroup"
  #scrollerRef
>
  <ng-container *ngFor="let group of scrollerRef.viewPortItems">
    <!-- 分组头部 -->
    <div class="group-header">
      <span>{{ group.groupTitle }}</span>
      <button (click)="toggleGroupAll(group)">
        {{ group.isAllExpanded ? '全部折叠' : '全部展开' }}
      </button>
    </div>
    <!-- 分组子项列表 -->
    <div class="group-children">
      <div *ngFor="let child of group.children; trackBy: trackByChild">
        <div class="child-header" (click)="toggleSingleItem(child, group)">
          子项标题:{{ child.content }}
        </div>
        <div class="child-content" *ngIf="child.isExpanded">
          子项展开后的内容区域
        </div>
      </div>
    </div>
  </ng-container>
</ngx-virtual-scroller>

注意:如果你的虚拟滚动设置了固定item高度,需要取消固定高度配置,或者在子项展开折叠后主动更新高度映射,避免滚动定位异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 16:54:01