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

Fluent UI GroupedList问题:同级文件夹无法同时显示文件与子文件夹

解决Fluent UI GroupedList同时展示文件与子文件夹的问题

核心问题分析

Fluent UI的GroupedList组件默认要求同一组内的项为同类型结构,你的原始数据将文件和子文件夹拆分为两个独立数组,导致组件无法同时渲染两类内容。解决思路是将文件与子文件夹统一为同一类型的列表项,通过标记区分类型后,自定义渲染逻辑实现差异化展示。

步骤1:转换数据结构

首先需要递归处理原始数据,把每个文件夹下的files和subFolderName合并为统一的items数组,每个项添加type标记区分文件/文件夹:

// 递归转换文件夹为GroupedList兼容的组结构
const transformFolderToGroup = (folder) => {
  // 合并文件与子文件夹为统一列表项
  const items = [
    // 转换文件
    ...folder.files.map(file => ({
      type: 'file',
      name: file,
      key: `${folder.folderName}-${file}` // 确保key唯一
    })),
    // 转换子文件夹(递归处理嵌套)
    ...folder.subFolderName.map(subFolder => ({
      type: 'folder',
      name: subFolder.folderName,
      key: `${folder.folderName}-${subFolder.folderName}`,
      ...transformFolderToGroup(subFolder)
    }))
  ];

  return {
    key: folder.folderName,
    name: folder.folderName,
    items: items
  };
};

// 你的原始数据
const originalData = [
  {
    "folderName": "Root",
    "files": ["file1.txt", "file2.txt"],
    "subFolderName": [
      { "folderName": "SubA", "files": [], "subFolderName": [{ "folderName": "SubA1", "files": ["doc.pdf"] }] }
    ]
  }
];

// 转换为GroupedList可用的groups结构
const groups = originalData.map(transformFolderToGroup);

步骤2:自定义GroupedList渲染逻辑

通过onRenderCell属性根据项的type渲染不同UI,同时利用组件内置的折叠功能处理文件夹层级:

import { GroupedList } from '@fluentui/react/lib/GroupedList';
import { ChevronDownIcon, ChevronRightIcon, FileIcon, FolderIcon } from '@fluentui/react/lib/Icon';

const FileFolderBrowser = () => {
  // 渲染单个列表项
  const onRenderCell = (item) => {
    if (item.type === 'folder') {
      return (
        <div style={{ display: 'flex', alignItems: 'center', padding: '8px 12px' }}>
          {/* 折叠/展开图标 */}
          {item.items.length > 0 ? (
            <ChevronDownIcon style={{ marginRight: '8px', cursor: 'pointer' }} />
          ) : (
            <ChevronRightIcon style={{ marginRight: '8px' }} />
          )}
          <FolderIcon style={{ marginRight: '8px', color: '#d83b01' }} />
          <span>{item.name}</span>
        </div>
      );
    } else {
      // 文件项渲染
      return (
        <div style={{ display: 'flex', alignItems: 'center', padding: '8px 12px' }}>
          <FileIcon style={{ marginRight: '8px', color: '#0078d4' }} />
          <span>{item.name}</span>
        </div>
      );
    }
  };

  // 渲染组标题(可选)
  const onRenderHeader = (group) => {
    return (
      <div style={{ padding: '10px 12px', fontWeight: '600', backgroundColor: '#f3f2f1' }}>
        {group.name}
      </div>
    );
  };

  return (
    <GroupedList
      groups={groups}
      onRenderCell={onRenderCell}
      onRenderHeader={onRenderHeader}
      collapseAllVisibility="visible"
      isHeaderVisible={true}
      // 若需自定义折叠状态,可通过onToggleCollapse维护状态
      // onToggleCollapse={(group) => {/* 处理折叠逻辑 */}}
    />
  );
};

export default FileFolderBrowser;

关键注意事项

  • 唯一key:所有项的key必须全局唯一,避免渲染冲突,建议用父文件夹名称拼接当前项名称生成。
  • 递归嵌套:子文件夹通过递归转换,自动继承组结构,实现层级展示。
  • 折叠状态:如需自定义折叠/展开逻辑,可通过onToggleCollapse事件维护每个组的状态,替代组件默认行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:43:16