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

如何用SPFx+React+PnP SP实现多SharePoint列表关联数据展示WebPart

解决SPFx中多列表数据关联与层级渲染的方案

一、并行获取三个列表的数据

用PnP SP的Promise.all同时请求三个列表的items,避免串行请求拖慢速度,同时指定需要的字段减少数据传输量:

import { sp } from "@pnp/sp/presets/all";

// 定义数据类型(增强类型提示,可选)
interface Category {
  Id: number;
  Title: string;
}

interface SubCategory {
  Id: number;
  Title: string;
  CategoryId: number; // 关联分类列表的Id字段
}

interface Project {
  Id: number;
  Title: string;
  CategoryId: number;
  SubCategoryId: number; // 关联子分类列表的Id字段
  // 可添加其他项目字段
}

// 获取所有数据的异步函数
const fetchAllData = async (): Promise<{categories: Category[], subCategories: SubCategory[], projects: Project[]}> => {
  try {
    // 并行发起三个列表的请求
    const [categories, subCategories, projects] = await Promise.all([
      sp.web.lists.getByTitle("分类列表").items.select("Id", "Title").get<Category[]>(),
      sp.web.lists.getByTitle("子分类列表").items.select("Id", "Title", "CategoryId").get<SubCategory[]>(),
      sp.web.lists.getByTitle("项目列表").items.select("Id", "Title", "CategoryId", "SubCategoryId").get<Project[]>(),
    ]);
    return { categories, subCategories, projects };
  } catch (error) {
    console.error("获取数据失败:", error);
    throw error;
  }
};

二、构建分类→子分类→项目的层级结构

先把数据转换成便于查询的分组对象,再组装成目标层级:

const buildHierarchy = (categories: Category[], subCategories: SubCategory[], projects: Project[]) => {
  // 按分类ID分组子分类
  const subCatsByCategory = subCategories.reduce((acc, subCat) => {
    const catId = subCat.CategoryId;
    if (!acc[catId]) acc[catId] = [];
    acc[catId].push(subCat);
    return acc;
  }, {} as Record<number, SubCategory[]>);

  // 按子分类ID分组项目
  const projectsBySubCat = projects.reduce((acc, project) => {
    const subCatId = project.SubCategoryId;
    if (!acc[subCatId]) acc[subCatId] = [];
    acc[subCatId].push(project);
    return acc;
  }, {} as Record<number, Project[]>);

  // 组装最终层级数据
  return categories.map(category => ({
    ...category,
    subCategories: subCatsByCategory[category.Id]?.map(subCat => ({
      ...subCat,
      projects: projectsBySubCat[subCat.Id] || []
    })) || []
  }));
};

三、React组件中渲染层级结构

在组件的useEffect中加载数据并构建层级,用CSS Grid实现子分类的3列布局:

import { useEffect, useState } from "react";
import styles from "./YourWebPart.module.scss";

const CategoryHierarchy = () => {
  const [hierarchy, setHierarchy] = useState<(Category & {subCategories: (SubCategory & {projects: Project[]})[]})[]>([]);

  useEffect(() => {
    const loadData = async () => {
      const { categories, subCategories, projects } = await fetchAllData();
      const builtHierarchy = buildHierarchy(categories, subCategories, projects);
      setHierarchy(builtHierarchy);
    };
    loadData();
  }, []);

  return (
    <div className={styles.container}>
      {hierarchy.map(category => (
        <div key={category.Id} className={styles.categorySection}>
          <h2 className={styles.categoryTitle}>{category.Title}</h2>
          {/* 3列网格布局展示子分类 */}
          <div className={styles.subCategoriesGrid}>
            {category.subCategories.map(subCat => (
              <div key={subCat.Id} className={styles.subCategoryCard}>
                <h3 className={styles.subCategoryTitle}>{subCat.Title}</h3>
                <ul className={styles.projectList}>
                  {subCat.projects.map(project => (
                    <li key={project.Id} className={styles.projectItem}>{project.Title}</li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
        </div>
      ))}
    </div>
  );
};

export default CategoryHierarchy;

四、SCSS样式示例(实现3列布局)

在对应的.module.scss文件中添加布局样式:

.container {
  padding: 1rem;
}

.categorySection {
  margin-bottom: 2rem;
}

.categoryTitle {
  font-size: 1.5rem;
  margin-bottom: 1rem;
  border-bottom: 2px solid #eee;
  padding-bottom: 0.5rem;
}

.subCategoriesGrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

.subCategoryCard {
  padding: 1rem;
  border: 1px solid #eee;
  border-radius: 4px;
  background-color: #f9f9f9;
}

.subCategoryTitle {
  font-size: 1.2rem;
  margin-bottom: 0.8rem;
}

.projectList {
  list-style-type: disc;
  padding-left: 1.5rem;
}

.projectItem {
  margin-bottom: 0.3rem;
}

注意事项

  • 确保列表中的关联字段(如子分类的CategoryId、项目的SubCategoryId)是正确的数字类型,避免关联失败。
  • 若列表数据量较大,建议添加分页或筛选条件,避免一次性加载过多数据影响性能。
  • 可根据实际需求调整字段名称、样式及展示内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 00:00:27