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

React单页应用动态生成站点地图页面方案咨询

实现React单页应用树形站点地图页面的方案

1. 给路由配置补充元信息

首先在你的路由数组里,给每个路由节点添加额外的元数据,比如显示标题、唯一ID、父节点ID、跳转路径等,方便后续构建树形结构。以react-router为例:

const routes = [
  {
    path: '/',
    element: <Home />,
    meta: { title: '首页', id: 'home', parentId: null }
  },
  {
    path: '/products',
    element: <Products />,
    meta: { title: '产品列表', id: 'products', parentId: null },
    children: [
      {
        path: 'detail/:id',
        element: <ProductDetail />,
        meta: { title: '产品详情', id: 'product-detail', parentId: 'products' }
      }
    ]
  },
  // 更多路由...
];

2. 把路由转换成树形数据结构

写个工具函数,递归遍历路由配置,把嵌套或扁平的路由转换成适合展示的树形结构:

function buildSiteMapTree(routes) {
  const tree = [];
  const routeMap = {};

  // 先把所有路由存入映射表
  routes.forEach(route => {
    routeMap[route.meta.id] = { ...route.meta, path: route.path, children: [] };
    // 处理嵌套子路由
    route.children?.forEach(child => {
      routeMap[child.meta.id] = { ...child.meta, path: `${route.path}/${child.path}`, children: [] };
    });
  });

  // 构建树形层级
  routes.forEach(route => {
    const currentNode = routeMap[route.meta.id];
    if (route.meta.parentId === null) {
      tree.push(currentNode);
    } else {
      routeMap[route.meta.parentId].children.push(currentNode);
    }
    // 关联嵌套子路由
    route.children?.forEach(child => {
      currentNode.children.push(routeMap[child.meta.id]);
    });
  });

  return tree;
}

3. 实现递归树形渲染组件

用递归组件渲染站点地图,结合react-router的Link组件实现跳转,还可以加上折叠/展开功能:

import { Link } from 'react-router-dom';
import { useState } from 'react';

function SiteMapNode({ node }) {
  const [isExpanded, setIsExpanded] = useState(true);
  const hasChildren = node.children?.length > 0;

  return (
    <div className="site-map-node">
      <div className="node-title" onClick={() => hasChildren && setIsExpanded(!isExpanded)}>
        {hasChildren && <span className="expand-icon">{isExpanded ? '▼' : '▶'}</span>}
        <Link to={node.path}>{node.title}</Link>
      </div>
      {hasChildren && isExpanded && (
        <div className="node-children">
          {node.children.map(child => (
            <SiteMapNode key={child.id} node={child} />
          ))}
        </div>
      )}
    </div>
  );
}

function SiteMapPage() {
  const siteMapTree = buildSiteMapTree(routes);

  return (
    <div className="site-map-container">
      <h1>站点地图</h1>
      <div className="site-map-tree">
        {siteMapTree.map(rootNode => (
          <SiteMapNode key={rootNode.id} node={rootNode} />
        ))}
      </div>
    </div>
  );
}

4. 处理动态参数路由

如果有带参数的路由(比如/products/detail/:id),要展示具体产品链接的话,需要从后端拉取数据后生成动态节点:

import { useEffect, useState } from 'react';

function SiteMapPage() {
  const [siteMapTree, setSiteMapTree] = useState([]);

  useEffect(() => {
    async function fetchDynamicData() {
      // 从后端获取产品列表
      const products = await fetch('/api/products').then(res => res.json());
      // 生成动态路由节点
      const dynamicNodes = products.map(product => ({
        id: `product-${product.id}`,
        title: product.name,
        path: `/products/detail/${product.id}`,
        parentId: 'product-detail'
      }));
      // 合并到原树形结构
      const originalTree = buildSiteMapTree(routes);
      const updatedTree = mergeDynamicNodes(originalTree, dynamicNodes);
      setSiteMapTree(updatedTree);
    }
    fetchDynamicData();
  }, []);

  // 合并动态节点的辅助函数
  function mergeDynamicNodes(tree, dynamicNodes) {
    const updatedTree = JSON.parse(JSON.stringify(tree));
    const nodeMap = {};

    // 递归遍历树,存入映射表
    function traverse(node) {
      nodeMap[node.id] = node;
      node.children?.forEach(traverse);
    }
    updatedTree.forEach(traverse);

    // 添加动态节点到对应父节点
    dynamicNodes.forEach(node => {
      nodeMap[node.parentId]?.children.push(node);
    });
    return updatedTree;
  }

  // 渲染逻辑...
}

5. 样式优化

给树形结构加基础样式,提升可读性:

.site-map-container {
  padding: 2rem;
}
.site-map-node {
  margin: 0.5rem 0;
}
.node-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
}
.expand-icon {
  font-size: 0.8rem;
}
.node-children {
  margin-left: 1.5rem;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 09:50:50