计算面包屑显示和解决 Antd 中 Menu 菜单高亮样式丢失问题

发布于:2022-12-08 ⋅ 阅读:(573) ⋅ 点赞:(0)

Breadcrumb 面包屑

Antd的面包屑组件是一个能够结合路由进行跳转页面的组件,其中对于路由的支持是react-router@3以及react-router@4。

Menu菜单高亮问题

问题描述:ant-design 的 Menu 自带菜单高亮样式。但是,当我们刷新页面时,Menu的高亮样式和伸缩状态会重置。如何解决这个问题呢?

修复目标:当我们刷新网页时,Menu 菜单的高亮样式和伸缩状态可以正常保留,且由当前 url 值所控制。

本篇文章你将学习到以下知识点:

  • 使用 react-router-dom(v5) 中相关的 Hooks API;
  • 计算属性 useMemo() 的使用;
  • 自定义封装 Hooks,实现代码逻辑的封装与复用;
  • 使用 ant-design 的 Menu 组件;
  • 如果可能,你还能学到更多其它知识。

自定义封装 useMenu()

import { useMemo } from 'react'
import { useLocation } from 'react-router-dom'
import { asyncRoutes } from '@/views'

// 通过useLocation访问当前url,根据url,在routes路由信息中遍历找到对应的key及其父级的key
export function useMenu () {
  const { pathname } = useLocation()
  // console.log('----pathname', pathname)
  // console.log('----asyncRoutes', asyncRoutes)
  return useMemo(()=>{
    let selectedKey = ''
    let openKey = ''
    // 用两层for写,更方便地退出循环
    asyncRoutes.forEach(ele => {
      if (!ele.children) {
        if (ele.path === pathname) {
          selectedKey = ele.key
        }
      }
      if (ele.children) {
        ele.children.forEach(ele2 => {
          // console.log('---ele2')
          if (ele2.path === pathname) {
            selectedKey = ele2.key
            openKey = ele.key
            // console.log('---ele2')
          }
        })
      }
    })
    // 坑:Menu高亮要求用 string[] 进行控制
    return [selectedKey+'', openKey+'']
  }, [pathname])
}

 Layout 中 左侧 Sider 组件代码:

import { Link } from 'react-router-dom'
import { useSelector } from 'react-redux'

import { Menu } from 'antd'
import {
  UserOutlined,
  VideoCameraOutlined,
  UploadOutlined,
} from '@ant-design/icons'

import { useMenu } from '@/hooks'

import logo from '@/assets/logo.png'

function getItem(label, key, icon, children, type) {
  return {
    key,
    icon,
    children,
    label,
    type,
  };
}

// 渲染Menu菜单
function createItems (routes) {
  const result = routes.map(ele => {
    if (ele.path) {
      if (!ele.hidden) {
        return getItem(
          <Link to={ele.path}>{ ele.label }</Link>
          ,ele.key, ele.icon)
      }
    } else {
      return getItem(
        ele.label,
        ele.key, ele.icon, createItems(ele.children))
    }
  })
  return result
}

const Logo = props => {
  const { collapsed } = props
  return (
    <div className={!collapsed?'logo2':'logo1'}>
      <img src={logo} alt="ght"/>
    </div>
  )
}

export default props => {

  const [selectedKey, openKey] = useMenu()
  // console.log('---useMenu', selectedKey, openKey)
  const { fixedLogo } = useSelector(state=>state.app)
  const { accessRoutes } = useSelector(state=>state.user)

  return (
    <div className="gh-sider">
      {
        fixedLogo && <Logo {...props} />
      }
      {/* 菜单渲染 */}
      <Menu
        theme="dark"
        mode="inline"
        selectedKeys={[selectedKey]}
        defaultOpenKeys={[openKey]}
        items={createItems(accessRoutes)}
      />
    </div>
  )
}

计算面包屑显示

 

export function useBreadcrumb () {
  const arr = [...asyncRoutes]
  const { pathname } = useLocation()
  let result = [arr[0]]  // 把首页添加面包屑中
  // 找二级菜单
  if (pathname !== '/dashboard') {
    for (let i=0; i<arr.length; i++) {
      if (arr[i].children) {
        for (let j=0; j<arr[i].children.length; j++) {
          if (arr[i].children[j].path === pathname) {
            result.push(arr[i])
            result.push(arr[i].children[j])
          }
        }
      }
    }
  }
  return result
}

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到