当前位置:   article > 正文

antd结合reactRouter实现侧边栏菜单动态渲染_react浮动侧边栏

react浮动侧边栏

目录

声明式方式

编程式方式

最终版本


声明式方式

目录结构是这个样子的

首先,需要安装react-router-dom和antd这两个插件(路由前面帖子有讲解)

yarn add react-router-dom antd     或      npm i react-router-dom antd --save

然后在index.js中做出配置

  1. import React from 'react'
  2. import ReactDOM from 'react-dom/client'
  3. import App from './App'
  4. // 这里路由采用了浏览器模式
  5. import { BrowserRouter as Router } from 'react-router-dom'
  6. // 一定引入antd的样式
  7. import 'antd/dist/antd.css'
  8. const root = ReactDOM.createRoot(document.getElementById('root'))
  9. root.render(
  10. <React.StrictMode>
  11. <Router>
  12. <App />
  13. </Router>
  14. </React.StrictMode>
  15. )

在router.js文件中写入路由规则(四级五级路由就再进行嵌套)

  1. import Index from '../pages/Index.jsx'
  2. import Demo from '../pages/Demo.jsx'
  3. import { HeartOutlined } from '@ant-design/icons'
  4. const routes = [
  5. {
  6. path: '/',
  7. element: <Index />,
  8. icon: <HeartOutlined />,
  9. label: '首页',
  10. },
  11. {
  12. path: '/demo',
  13. element: <Demo />,
  14. icon: <HeartOutlined />,
  15. label: '朋友',
  16. },
  17. {
  18. path: '/about',
  19. label: '关于',
  20. icon: <HeartOutlined />,
  21. children: [
  22. {
  23. path: 'music',
  24. element: <Demo />,
  25. label: '音乐',
  26. icon: <HeartOutlined />,
  27. },
  28. {
  29. path: 'movie',
  30. element: <Demo />,
  31. label: '电影',
  32. icon: <HeartOutlined />,
  33. },
  34. ],
  35. },
  36. {
  37. path: '/my',
  38. label: '我的',
  39. icon: <HeartOutlined />,
  40. children: [
  41. {
  42. path: 'money',
  43. label: '钱包',
  44. icon: <HeartOutlined />,
  45. children: [
  46. {
  47. path: 'yue',
  48. element: <Demo />,
  49. label: '余额',
  50. icon: <HeartOutlined />,
  51. },
  52. ],
  53. },
  54. {
  55. path: 'message',
  56. element: <Demo />,
  57. label: '信息',
  58. icon: <HeartOutlined />,
  59. },
  60. ],
  61. },
  62. ]
  63. export default routes

最后在App.js文件中引入布局组件,实现渲染

  1. import { Layout, Menu } from 'antd'
  2. import React from 'react'
  3. // 引入路由规则文件
  4. import routes from './router/router.js'
  5. import { Link, useRoutes } from 'react-router-dom'
  6. const { Sider, Content, Header } = Layout
  7. export default function App() {
  8. const element = useRoutes(routes)
  9. // Menu组件通过指定items属性,进行菜单渲染
  10. const items = []
  11. // 对路由规则数组进行遍历,并对其进行改造,改造成与Menu的items属性相同的结构
  12. routes.forEach((item) => {
  13. items.push({
  14. label: <Link to={item.path}>{item.label}</Link>,
  15. key: item.path,
  16. icon: item.icon,
  17. children:
  18. item.children &&
  19. item.children.map((child) => {
  20. return {
  21. label: <Link to={item.path + '/' + child.path}>{child.label}</Link>,
  22. key: item.path + '/' + child.path,
  23. icon: child.icon,
  24. children:
  25. child.children &&
  26. child.children.map((sun) => {
  27. return {
  28. label: (
  29. <Link to={item.path + '/' + child.path + '/' + sun.path}>
  30. {sun.label}
  31. </Link>
  32. ),
  33. key: item.path + '/' + child.path + '/' + sun.path,
  34. icon: sun.icon,
  35. }
  36. }),
  37. }
  38. }),
  39. })
  40. })
  41. return (
  42. <>
  43. <Layout>
  44. <Sider theme="dark">
  45. <div
  46. style={{
  47. height: '28px',
  48. margin: '16px',
  49. background: 'rgba(255, 255, 255, 0.2)',
  50. }}
  51. />
  52. <Menu theme="dark" mode="inline" items={items}></Menu>
  53. </Sider>
  54. <Layout>
  55. <Header></Header>
  56. <Content>{element}</Content>
  57. </Layout>
  58. </Layout>
  59. </>
  60. )
  61. }

这是Menu组件的items结构

最终的效果如下

编程式方式

目录结构是这样的

首先,需要安装react-router-dom和antd这两个插件(路由前面帖子有讲解)

yarn add react-router-dom antd     或      npm i react-router-dom antd --save

然后在index.js中做出配置

  1. import React from 'react'
  2. import ReactDOM from 'react-dom/client'
  3. import App from './App'
  4. // 这里路由采用了浏览器模式
  5. import { BrowserRouter as Router } from 'react-router-dom'
  6. // 一定引入antd的样式
  7. import 'antd/dist/antd.css'
  8. const root = ReactDOM.createRoot(document.getElementById('root'))
  9. root.render(
  10. <React.StrictMode>
  11. <Router>
  12. <App />
  13. </Router>
  14. </React.StrictMode>
  15. )

在router.js文件中写入路由规则(四级五级路由就再进行嵌套)

  1. import Home from '../pages/Home'
  2. import Movie from '../pages/Movie'
  3. import Music from '../pages/Music'
  4. import Money from '../pages/Money'
  5. import Person from '../pages/Person'
  6. import { SmileOutlined } from '@ant-design/icons'
  7. const routes = [
  8. {
  9. path: '/',
  10. label: '首页',
  11. element: <Home />,
  12. icon: <SmileOutlined />,
  13. },
  14. {
  15. path: '/about',
  16. label: '关于',
  17. icon: <SmileOutlined />,
  18. children: [
  19. {
  20. path: 'music',
  21. label: '音乐',
  22. element: <Music />,
  23. icon: <SmileOutlined />,
  24. },
  25. {
  26. path: 'movie',
  27. label: '电影',
  28. element: <Movie />,
  29. icon: <SmileOutlined />,
  30. },
  31. ],
  32. },
  33. {
  34. path: '/my',
  35. label: '我的',
  36. icon: <SmileOutlined />,
  37. children: [
  38. {
  39. path: 'money',
  40. label: '余额',
  41. element: <Money />,
  42. icon: <SmileOutlined />,
  43. },
  44. {
  45. path: 'message',
  46. label: '信息',
  47. icon: <SmileOutlined />,
  48. children: [
  49. {
  50. path: 'person',
  51. label: '个人信息',
  52. element: <Person />,
  53. icon: <SmileOutlined />,
  54. },
  55. ],
  56. },
  57. ],
  58. },
  59. ]
  60. export default routes

 最后在App.js文件中引入布局组件,实现渲染

  1. import { useState } from 'react'
  2. import { Layout, Menu, Switch } from 'antd'
  3. import { useRoutes, useNavigate } from 'react-router-dom'
  4. import routes from './router/router'
  5. const { Header, Sider, Content } = Layout
  6. function App() {
  7. let element = useRoutes(routes)
  8. const navigate = useNavigate()
  9. const items = []
  10. routes.forEach((item) => {
  11. items.push({
  12. label: item.label,
  13. key: item.path,
  14. icon: item.icon,
  15. children:
  16. item.children &&
  17. item.children.map((child) => {
  18. return {
  19. label: child.label,
  20. key: item.path + '/' + child.path,
  21. icon: child.icon,
  22. children:
  23. child.children &&
  24. child.children.map((sun) => {
  25. return {
  26. label: sun.label,
  27. key: item.path + '/' + child.path + '/' + sun.path,
  28. icon: sun.icon,
  29. // 有四级五级菜单就接着写,最好用递归的方式,但是我不会写
  30. }
  31. }),
  32. }
  33. }),
  34. })
  35. })
  36. const [theme, setTheme] = useState('dark')
  37. const changeTheme = (value) => {
  38. setTheme(value ? 'dark' : 'light')
  39. }
  40. const onClick = (e) => {
  41. navigate(e.key)
  42. }
  43. return (
  44. <div className="App">
  45. <Layout>
  46. <Sider>
  47. <Switch
  48. checked={theme === 'dark'}
  49. onChange={changeTheme}
  50. checkedChildren="Dark"
  51. unCheckedChildren="Light"
  52. />
  53. <Menu theme={theme} onClick={onClick} mode="inline" items={items} />
  54. </Sider>
  55. <Layout>
  56. <Header style={{ background: '#ccc' }}>Header</Header>
  57. <Content>{element}</Content>
  58. </Layout>
  59. </Layout>
  60. </div>
  61. )
  62. }
  63. export default App

最终效果

最终版本

  • 包含了懒加载,直接把路由文件改造成Menu组件需要的结构,这样Menu组件只需要引入router.js文件,并把items属性的值为路由规则即可

router.js

  1. import { lazy, Suspense } from 'react'
  2. import Home from '../pages/Home'
  3. import { SmileOutlined } from '@ant-design/icons'
  4. // 路由懒加载
  5. const Music = lazy(() => import('../pages/Music'))
  6. const Movie = lazy(() => import('../pages/Movie'))
  7. const Money = lazy(() => import('../pages/Money'))
  8. const Person = lazy(() => import('../pages/Person'))
  9. const routes = [
  10. {
  11. path: '/',
  12. key: '/',
  13. label: '首页',
  14. element: <Home />,
  15. icon: <SmileOutlined />,
  16. },
  17. {
  18. path: '/about',
  19. key: '/about',
  20. label: '关于',
  21. icon: <SmileOutlined />,
  22. children: [
  23. {
  24. path: 'music',
  25. key: 'music',
  26. label: '音乐',
  27. element: (
  28. <Suspense fallback={<></>}>
  29. <Music />
  30. </Suspense>
  31. ),
  32. icon: <SmileOutlined />,
  33. },
  34. {
  35. path: 'movie',
  36. key: 'movie',
  37. label: '电影',
  38. element: (
  39. <Suspense fallback={<></>}>
  40. <Movie />
  41. </Suspense>
  42. ),
  43. icon: <SmileOutlined />,
  44. },
  45. ],
  46. },
  47. {
  48. path: '/my',
  49. key: '/my',
  50. label: '我的',
  51. icon: <SmileOutlined />,
  52. children: [
  53. {
  54. path: 'money',
  55. key: 'money',
  56. label: '余额',
  57. element: (
  58. <Suspense fallback={<></>}>
  59. <Money />
  60. </Suspense>
  61. ),
  62. icon: <SmileOutlined />,
  63. },
  64. {
  65. path: 'message',
  66. key: 'message',
  67. label: '信息',
  68. icon: <SmileOutlined />,
  69. children: [
  70. {
  71. path: 'person',
  72. key: 'person',
  73. label: '个人信息',
  74. element: (
  75. <Suspense fallback={<></>}>
  76. <Person />
  77. </Suspense>
  78. ),
  79. icon: <SmileOutlined />,
  80. },
  81. ],
  82. },
  83. ],
  84. },
  85. ]
  86. export default routes

App.js

  1. import { Layout, Menu } from 'antd'
  2. import { useRoutes, useNavigate } from 'react-router-dom'
  3. import routes from './router/router'
  4. const { Header, Sider, Content } = Layout
  5. function App() {
  6. let element = useRoutes(routes)
  7. const navigate = useNavigate()
  8. const onClick = (e) => {
  9. let path = e.keyPath.reverse().join('/')
  10. navigate(path)
  11. }
  12. return (
  13. <div className="App">
  14. <Layout>
  15. <Sider>
  16. <Menu theme="dark" onClick={onClick} mode="inline" items={routes} />
  17. </Sider>
  18. <Layout>
  19. <Header style={{ background: '#ccc' }}>Header</Header>
  20. <Content>{element}</Content>
  21. </Layout>
  22. </Layout>
  23. </div>
  24. )
  25. }
  26. export default App

效果如下

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/113136
推荐阅读
相关标签
  

闽ICP备14008679号