❤ React体系28-antd左侧菜单antd5最新版本和Router(v6)实现(2024-06最新)
1、 antd页面布局重编
之前我们的布局导航都是自己手写的方式进行实现的,现在我们就改成antd里面的方式,使用antd的伸缩菜单的方式,布局上面采用的是第四种这种风格
之前我们自己定义的结构部分是这样子的
js
{/* 自定义结构部分 */}
<div className="adminpage">
<aside className={menuState ? 'nav-left collapsetrue' : 'nav-left collapsefalse'}>
<Navbarleft></Navbarleft>
</aside>
<main className={menuState ? 'nav-right nav-right-collapsetrue' : 'nav-right nav-right-collapsefalse'}>
<header className="nav-right-head">
{menuState?(<img onClick={()=>{handleClickcollapsesvg(false)}} className="collapsesvg" src={collapsefalsesvg} alt="" />):(<img onClick={()=>{handleClickcollapsesvg(true)}} className="collapsesvg" src={collapsetruesvg} alt="" />)}
</header>
<main className="nav-right-body">
<section className="nexusbcbox">
<Outlet></Outlet>
</section>
</main>
<footer className="nav-right-foot"></footer>
</main>
</div>
现在我们就来改造一下这部分
引入antd的要使用的组件部分
js
引入antd的要使用的组件部分
import { Flex, Layout,Button } from 'antd';
const { Header, Footer, Sider, Content } = Layout;
引进antd的样式部分
js
const headerStyle: React.CSSProperties = {
textAlign: 'center',
color: '#fff',
height: 64,
paddingInline: 48,
lineHeight: '64px',
backgroundColor: '#4096ff',
};
const contentStyle: React.CSSProperties = {
textAlign: 'center',
minHeight: 120,
lineHeight: '120px',
color: '#fff',
backgroundColor: '#0958d9',
};
const siderStyle: React.CSSProperties = {
textAlign: 'center',
lineHeight: '120px',
color: '#fff',
backgroundColor: '#1677ff',
};
const footerStyle: React.CSSProperties = {
textAlign: 'center',
color: '#fff',
backgroundColor: '#4096ff',
};
const layoutStyle = {
borderRadius: 8,
overflow: 'hidden',
width: 'calc(100% - 8px)',
maxWidth: 'calc(100% - 8px)',
};
引进antd的结构部分
js
<Flex gap="middle" wrap>
<Layout style={layoutStyle}>
<Sider width="25%" style={siderStyle}>
Sider
</Sider>
<Layout>
<Header style={headerStyle}>
Header
</Header>
<Content style={contentStyle}>
Content
</Content>
<Footer style={footerStyle}>
Footer
</Footer>
</Layout>
</Layout>
</Flex>
预览一下,还不错
接下来我们就完善一下我们的结构,把之前的组件都引入放进去
2、 antd导航菜单重编
接下来我们用antd重新绘制我们左侧的导航菜单
然后我们把左右布局做好
需要的思路是:
flex左右布局,右侧块元素随着左侧块元素的变化自动填充剩余宽度
js
<Layout style={{ minHeight: '100vh' }}>
<Sider trigger={null} collapsible collapsed={collapsed}>
<div className="logo" />
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
<Menu.Item key="1" icon={<UserOutlined />}>
Option 1
</Menu.Item>
<Menu.Item key="2" icon={<UserOutlined />}>
Option 2
</Menu.Item>
<Menu.Item key="3" icon={<UserOutlined />}>
Option 3
</Menu.Item>
</Menu>
</Sider>
<Layout className="site-layout">
<Header className="site-layout-background" style={{ padding: 0 }}>
<Button
type="primary"
onClick={toggleCollapsed}
style={{
marginBottom: 16,
}}
>
{collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
</Button>
</Header>
<Content
className="site-layout-background"
style={{
margin: '24px 16px',
padding: 24,
minHeight: 280,
flex: 'auto', // 让右侧块元素自动填充剩余宽度
}}
>
Content
</Content>
</Layout>
</Layout>
简单看一下我们的效果
这里需要注意的就是,我们菜单是否展开的状态不是写到Menu
上而是要放到 Sider
上
左侧的应该放到右边神身上
然后更正以后看一眼我们的布局,正常
目前我们可以看到,实现伸缩都是在一个组件里面,那么我们如何拆离并且可以在任意地方控制这个菜单的伸缩呢?
3、 菜单伸缩全局状态
接下来我们就将菜单更改为头部组件控制,也就是抽离使用我们全局菜单状态,之前我们已经写好了
将头部菜单给抽离为单个组件然后放入我们的全局状态,当点击的时候操作这个状态行为
在我们的admin主要的页面之中只需要引入组件,在useEffect之中加载的时候加入menuState
即可
这样,我们在任意地方都可以使用这个全局菜单状态控制组件。
4、路由优化
createBrowserRouter(react router v6.4.0 版本推出 )
之前我们的路由都是自己手写的路由,现在我们优化成根据路由自动生成对应的路由
也就是把这一部分更改成为活数据
接下来完善我们的路由,也就是页面src/router/index.tsx
createXXRouter
是官方在 v6.4.0 版本推出的,称为 Data Router,支持 Data API 。
我们可以使用createBrowserRouter
创建 Router 实例,传入RouterProvider
使用。
js
// App.jsx
import { createBrowserRouter, RouterProvider } from "react-router-dom";
// import route components
const router = createBrowserRouter([
{
path: "/",
element: <Home />,
},
{
path: "/about",
element: <About />,
},
]);
export default function App() {
return <RouterProvider router={router} />;
}
接下来就用这种方式改造我们的路由
先随便输出一个路径可以看到
使用官方版本v6.4来写我们的路由
js
import { BrowserRouter as Router, Routes, Route ,Navigate,createBrowserRouter, RouterProvider } from 'react-router-dom';
const routerv64 = createBrowserRouter([ ....])
const GetRouter = () => {
return (
<>
<RouterProvider router={routerv64} />
</>
);
}
export default GetRouter
然后我们预览看看,这个时候发现给我们报错了
Absolute route path "/role" nested under path "/admin" is not valid. An absolute child route path must start with the combined path of all its parent routes.
之前可能因为我们写法是这样,我们更改一下
js
{
path: "/admin",
element: <Admin></Admin>,
children: [
{
path: "/home",
element: <Adminhome></Adminhome>,
},]
}
刷新一下,页面正确!
5、antd侧边栏菜单路由渲染
优化一下我们的路由,然后输出查看一下可以发现:
我们尝试拿其中的数据
我们后台系统真正需要的其实是这部分,所以我们抽离出来
常见的我们的导出分为以下几种方式:
js
// 默认导出
import MyComponent from './MyComponent';
// 命名导出
import { ComponentA, ComponentB } from './MyComponents';
// 默认导出和命名导出混用
import DefaultComponent, { NamedComponentA, NamedComponentB } from './MyComponents';
这里我们已经拿到了属于后台的路由,然后我们进行渲染
问题出现了,这里砸门拿到的路由确实是数组,但是却一直没法直接把一个数组值给另外一个呢
我们重新清除缓存,然后直接拿快渲染一下,证明我们是没错的。
这种方式我们直接自己循环进行实现,自己可以自由组合。
这时候我发现,新版本已经换了写法。
所以。前端老换东西真是很恶心人