目录

声明式方式

编程式方式

最终版本


声明式方式

目录结构是这个样子的

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

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

然后在index.js中做出配置

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
// 这里路由采用了浏览器模式
import { BrowserRouter as Router } from 'react-router-dom'
// 一定引入antd的样式
import 'antd/dist/antd.css'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <Router>
      <App />
    </Router>
  </React.StrictMode>
)

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

import Index from '../pages/Index.jsx'
import Demo from '../pages/Demo.jsx'
import { HeartOutlined } from '@ant-design/icons'

const routes = [
  {
    path: '/',
    element: <Index />,
    icon: <HeartOutlined />,
    label: '首页',
  },
  {
    path: '/demo',
    element: <Demo />,
    icon: <HeartOutlined />,
    label: '朋友',
  },
  {
    path: '/about',
    label: '关于',
    icon: <HeartOutlined />,
    children: [
      {
        path: 'music',
        element: <Demo />,
        label: '音乐',
        icon: <HeartOutlined />,
      },
      {
        path: 'movie',
        element: <Demo />,
        label: '电影',
        icon: <HeartOutlined />,
      },
    ],
  },
  {
    path: '/my',
    label: '我的',
    icon: <HeartOutlined />,
    children: [
      {
        path: 'money',
        label: '钱包',
        icon: <HeartOutlined />,
        children: [
          {
            path: 'yue',
            element: <Demo />,
            label: '余额',
            icon: <HeartOutlined />,
          },
        ],
      },
      {
        path: 'message',
        element: <Demo />,
        label: '信息',
        icon: <HeartOutlined />,
      },
    ],
  },
]

export default routes

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

import { Layout, Menu } from 'antd'
import React from 'react'
// 引入路由规则文件
import routes from './router/router.js'
import { Link, useRoutes } from 'react-router-dom'

const { Sider, Content, Header } = Layout

export default function App() {
  const element = useRoutes(routes)
  // Menu组件通过指定items属性,进行菜单渲染
  const items = []
  // 对路由规则数组进行遍历,并对其进行改造,改造成与Menu的items属性相同的结构
  routes.forEach((item) => {
    items.push({
      label: <Link to={item.path}>{item.label}</Link>,
      key: item.path,
      icon: item.icon,
      children:
        item.children &&
        item.children.map((child) => {
          return {
            label: <Link to={item.path + '/' + child.path}>{child.label}</Link>,
            key: item.path + '/' + child.path,
            icon: child.icon,
            children:
              child.children &&
              child.children.map((sun) => {
                return {
                  label: (
                    <Link to={item.path + '/' + child.path + '/' + sun.path}>
                      {sun.label}
                    </Link>
                  ),
                  key: item.path + '/' + child.path + '/' + sun.path,
                  icon: sun.icon,
                }
              }),
          }
        }),
    })
  })
  return (
    <>
      <Layout>
        <Sider theme="dark">
          <div
            style={
   {
              height: '28px',
              margin: '16px',
              background: 'rgba(255, 255, 255, 0.2)',
            }}
          />
          <Menu theme="dark" mode="inline" items={items}></Menu>
        </Sider>
        <Layout>
          <Header></Header>
          <Content>{element}</Content>
        </Layout>
      </Layout>
    </>
  )
}

这是Menu组件的items结构

最终的效果如下

编程式方式

目录结构是这样的

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

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

然后在index.js中做出配置

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
// 这里路由采用了浏览器模式
import { BrowserRouter as Router } from 'react-router-dom'
// 一定引入antd的样式
import 'antd/dist/antd.css'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <Router>
      <App />
    </Router>
  </React.StrictMode>
)

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

import Home from '../pages/Home'
import Movie from '../pages/Movie'
import Music from '../pages/Music'
import Money from '../pages/Money'
import Person from '../pages/Person'
import { SmileOutlined } from '@ant-design/icons'

const routes = [
  {
    path: '/',
    label: '首页',
    element: <Home />,
    icon: <SmileOutlined />,
  },
  {
    path: '/about',
    label: '关于',
    icon: <SmileOutlined />,
    children: [
      {
        path: 'music',
        label: '音乐',
        element: <Music />,
        icon: <SmileOutlined />,
      },
      {
        path: 'movie',
        label: '电影',
        element: <Movie />,
        icon: <SmileOutlined />,
      },
    ],
  },
  {
    path: '/my',
    label: '我的',
    icon: <SmileOutlined />,
    children: [
      {
        path: 'money',
        label: '余额',
        element: <Money />,
        icon: <SmileOutlined />,
      },
      {
        path: 'message',
        label: '信息',
        icon: <SmileOutlined />,
        children: [
          {
            path: 'person',
            label: '个人信息',
            element: <Person />,
            icon: <SmileOutlined />,
          },
        ],
      },
    ],
  },
]

export default routes

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

import { useState } from 'react'
import { Layout, Menu, Switch } from 'antd'
import { useRoutes, useNavigate } from 'react-router-dom'
import routes from './router/router'
const { Header, Sider, Content } = Layout

function App() {
  let element = useRoutes(routes)
  const navigate = useNavigate()
  const items = []
  routes.forEach((item) => {
    items.push({
      label: item.label,
      key: item.path,
      icon: item.icon,
      children:
        item.children &&
        item.children.map((child) => {
          return {
            label: child.label,
            key: item.path + '/' + child.path,
            icon: child.icon,
            children:
              child.children &&
              child.children.map((sun) => {
                return {
                  label: sun.label,
                  key: item.path + '/' + child.path + '/' + sun.path,
                  icon: sun.icon,
                  // 有四级五级菜单就接着写,最好用递归的方式,但是我不会写
                }
              }),
          }
        }),
    })
  })
  const [theme, setTheme] = useState('dark')

  const changeTheme = (value) => {
    setTheme(value ? 'dark' : 'light')
  }
  const onClick = (e) => {
    navigate(e.key)
  }
  return (
    <div className="App">
      <Layout>
        <Sider>
          <Switch
            checked={theme === 'dark'}
            onChange={changeTheme}
            checkedChildren="Dark"
            unCheckedChildren="Light"
          />
          <Menu theme={theme} onClick={onClick} mode="inline" items={items} />
        </Sider>
        <Layout>
          <Header style={
   { background: '#ccc' }}>Header</Header>
          <Content>{element}</Content>
        </Layout>
      </Layout>
    </div>
  )
}

export default App

最终效果

最终版本

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

router.js

import { lazy, Suspense } from 'react'
import Home from '../pages/Home'
import { SmileOutlined } from '@ant-design/icons'

// 路由懒加载
const Music = lazy(() => import('../pages/Music'))
const Movie = lazy(() => import('../pages/Movie'))
const Money = lazy(() => import('../pages/Money'))
const Person = lazy(() => import('../pages/Person'))

const routes = [
  {
    path: '/',
    key: '/',
    label: '首页',
    element: <Home />,
    icon: <SmileOutlined />,
  },
  {
    path: '/about',
    key: '/about',
    label: '关于',
    icon: <SmileOutlined />,
    children: [
      {
        path: 'music',
        key: 'music',
        label: '音乐',
        element: (
          <Suspense fallback={<></>}>
            <Music />
          </Suspense>
        ),
        icon: <SmileOutlined />,
      },
      {
        path: 'movie',
        key: 'movie',
        label: '电影',
        element: (
          <Suspense fallback={<></>}>
            <Movie />
          </Suspense>
        ),
        icon: <SmileOutlined />,
      },
    ],
  },
  {
    path: '/my',
    key: '/my',
    label: '我的',
    icon: <SmileOutlined />,
    children: [
      {
        path: 'money',
        key: 'money',
        label: '余额',
        element: (
          <Suspense fallback={<></>}>
            <Money />
          </Suspense>
        ),
        icon: <SmileOutlined />,
      },
      {
        path: 'message',
        key: 'message',
        label: '信息',
        icon: <SmileOutlined />,
        children: [
          {
            path: 'person',
            key: 'person',
            label: '个人信息',
            element: (
              <Suspense fallback={<></>}>
                <Person />
              </Suspense>
            ),
            icon: <SmileOutlined />,
          },
        ],
      },
    ],
  },
]

export default routes

App.js

import { Layout, Menu } from 'antd'
import { useRoutes, useNavigate } from 'react-router-dom'
import routes from './router/router'
const { Header, Sider, Content } = Layout

function App() {
  let element = useRoutes(routes)
  const navigate = useNavigate()

  const onClick = (e) => {
    let path = e.keyPath.reverse().join('/')
    navigate(path)
  }
  return (
    <div className="App">
      <Layout>
        <Sider>
          <Menu theme="dark" onClick={onClick} mode="inline" items={routes} />
        </Sider>
        <Layout>
          <Header style={
   { background: '#ccc' }}>Header</Header>
          <Content>{element}</Content>
        </Layout>
      </Layout>
    </div>
  )
}

export default App

效果如下

原文链接:https://blog.csdn.net/qq_52845451/article/details/127459243

最后修改:2023 年 10 月 30 日
如果觉得我的文章对你有用,请随意赞赏