实现页面保持和组件抽取

Tutorial: React路由案例 Category: React Published: 2026-04-07 13:58:26 Views: 20 Likes: 0 Comments: 0
  1. Home 页面组件提取

    import React, { useState } from "react";
    import { Breadcrumb, Layout, theme } from "antd";
    import { Outlet } from "react-router-dom";
    // 组件
    import HomeMenu from "./HomeMenu";
    
    const { Header, Content, Footer, Sider } = Layout;
    
    const Home: React.FC = () => {
      const [collapsed, setCollapsed] = useState(false);
      const {
        token: { colorBgContainer },
      } = theme.useToken();
    
      return (
        <Layout style={{ minHeight: "100vh" }}>
          {/* 侧边栏 */}
          <Sider
            collapsible
            collapsed={collapsed}
            onCollapse={(value) => setCollapsed(value)}
          >
            <div
              style={{
                height: 32,
                margin: 16,
                background: "rgba(255, 255, 255, 0.2)",
              }}
            />
            {/* 使用组件 */}
            <HomeMenu />
          </Sider>
    
          {/* 右边 */}
          <Layout className="site-layout">
            {/* 头部区域 */}
            <Header style={{ paddingLeft: 16, background: colorBgContainer }}>
              <Breadcrumb style={{ lineHeight: "64px" }}>
                <Breadcrumb.Item>User</Breadcrumb.Item>
                <Breadcrumb.Item>Bill</Breadcrumb.Item>
              </Breadcrumb>
            </Header>
    
            {/* 内容区 */}
            <Content
              style={{
                margin: "16px 16px 0",
                background: colorBgContainer,
              }}
            >
              <Outlet />
            </Content>
    
            {/* 底部, 高度与左边保持一直 */}
            <Footer
              style={{ padding: 0, textAlign: "center", lineHeight: "48px" }}
            >
              Ant Design ©2018 Created by Ant UED
            </Footer>
          </Layout>
        </Layout>
      );
    };
    
    export default Home;
    
  2. 组件 src\pages\Home\HomeMenu.tsx

    import React, { useState } from "react";
    import { Menu, MenuProps } from "antd";
    import { useNavigate, useLocation } from "react-router-dom";
    import {
      DesktopOutlined,
      FileOutlined,
      PieChartOutlined,
      TeamOutlined,
      UserOutlined,
    } from "@ant-design/icons";
    
    type MenuItem = Required<MenuProps>["items"][number];
    
    function getItem(
      label: React.ReactNode,
      key: React.Key,
      icon?: React.ReactNode,
      children?: MenuItem[]
    ): MenuItem {
      return {
        key,
        icon,
        children,
        label,
      } as MenuItem;
    }
    
    const tabItem: MenuItem[] = [
      getItem("栏目一", "/page1", <PieChartOutlined />),
      getItem("栏目二", "/page2", <DesktopOutlined />),
      getItem("栏目三", "sub1", <UserOutlined />, [
        getItem("三目一", "3"),
        getItem("三目二", "4"),
        getItem("三目三", "5"),
      ]),
      getItem("栏目四", "sub2", <TeamOutlined />, [
        getItem("四目一", "6"),
        getItem("四目二", "8"),
      ]),
      getItem("栏目五", "9", <FileOutlined />),
    ];
    
    const HomeMenu = () => {
      // 获取当前pathname
      const { pathname } = useLocation();
      const navitateTo = useNavigate();
      // 默认展开项通过判断pathname来保持
      const [openKeys, setOpenKeys] = useState([
        pathname.split("/").length > 1 ? pathname.split("/")[1] : "",
      ]);
    
      // 页面切换
      const menuClick = (key: string) => {
        navitateTo(key);
      };
    
      // 设置默认只展开一个二级目录
      const onOpenChange = (keys: string[]) => {
        setOpenKeys([keys[keys.length - 1]]);
      };
    
      return (
        <Menu
          theme="dark"
          defaultSelectedKeys={[pathname]}
          mode="inline"
          items={tabItem}
          onClick={(e) => menuClick(e.key)}
          onOpenChange={onOpenChange}
          openKeys={openKeys}
        />
      );
    };
    
    export default HomeMenu;
    
  3. 删除 config 目录 => src\pages\config