ThatManK Mobile Article

实现页面保持和组件抽取

Category: React Tutorial: React路由案例 Published: 2026-04-07 13:58 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;
  1. 组件 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;
  1. 删除 config 目录 => src\pages\config