zoukankan      html  css  js  c++  java
  • react 封装antd menu组件,路由懒加载,可折叠,可配置显示和隐藏,刷新后选择正确的菜单,打开正确的submenu

    import React, { useEffect, useState, useMemo } from 'react'
    import { Menu } from 'antd'
    import { connect } from 'react-redux'
    import { withRouter } from 'react-router-dom'
    import Icon from '../../../components/light/Icon'
    import Logo from './Logo'
    
    const { SubMenu } = Menu
    
    function Sidebar(props) {
      const {
        router,
        location: { pathname },
        theme,
        selectedKeys,
        collapsed,
      } = props
    
      const [openKeys, setOpenKeys] = useState([])
    
      const defaultOpenKeysFn = () => {
        const arr = []
        let myPathname = pathname.replace(/(/+$)/g, '')
        let arrTemp = myPathname.split('/')
        if (arrTemp.length > 4) {
          for (let i = 4; i < arrTemp.length; i++) {
            arr.push(arrTemp.slice(0, i).join('/'))
          }
        }
        return arr
      }
    
      const handleNav = (path) => {
        //props.onSetState(['selectedKeys'], path)
        props.history.push(path)
      }
    
      const isFirstLevel = (item) => {
        const pathLength = item.key.split('/').length
        return pathLength === 4
      }
    
      // 只有router、collapsed变化时才会重新渲染sidebarDom,useMemo函数可以起到性能优化的作用
      const sidebarDom = useMemo(() => {
        const sidebarRender = (arr) => {
          return arr.map((item) => {
            if (item.children) {
              if (item.isVisible) {
                // 一级子菜单折叠时使用大图标
                return (
                  <SubMenu
                    key={item.key}
                    title={item.title}
                    className={item.className ? item.className : ''}
                    icon={
                      item.icon ? (
                        <span className="anticon anticon-appstore m-sidebar-icon-wrap">
                          <Icon
                            name={item.icon}
                            className={`m-sidebar-icon ${
                              collapsed && isFirstLevel(item)
                                ? 'big'
                                : ''
                            }`}
                          ></Icon>
                        </span>
                      ) : null
                    }
                  >
                    {sidebarRender(item.children)}
                  </SubMenu>
                )
              } else {
                return null
              }
            } else {
              // 使用span包裹Icon组件,并添加antd的className才能正确使用Menu的icon属性
              // 折叠时使用大图标
              if (item.isVisible) {
                // 有些菜单只在开发环境展示
                if (!item.isDevMenu || process.env.REACT_APP_MODE === 'dev'){
                  if(item.hiddenMenu!==false){
                    return (
                      <Menu.Item
                        key={item.path}
                        className={item.className ? item.className : ''}
                        onClick={() => handleNav(item.path)}
                        icon={
                          item.icon ? (
                            <span className="anticon anticon-appstore m-sidebar-icon-wrap">
                            <Icon
                              name={item.icon}
                              className={`m-sidebar-icon ${collapsed ? 'big' : ''}`}
                            ></Icon>
                          </span>
                          ) : null
                        }
                      >
                        <span>{item.title}</span>
                      </Menu.Item>
                    )
                  }else{
                    return null;
                  }
                } else {
                  return null
                }
              } else {
                return null
              }
            }
          })
        }
    
        return sidebarRender(router.toJS())
        // eslint-disable-next-line
      }, [router, collapsed])
    
      const handleOpenChange = (openKeys) => {
        setOpenKeys(openKeys)
      }
    
      useEffect(() => {
        props.onSetState(['selectedKeys'], pathname)
        // eslint-disable-next-line
      }, [pathname])
    
      useEffect(() => {
        if (!collapsed) {
          setOpenKeys(defaultOpenKeysFn())
        }
        // eslint-disable-next-line
      }, [collapsed])
    
      return (
        <Menu
          selectedKeys={[selectedKeys]}
          openKeys={openKeys}
          style={{  collapsed ? 80 : 256, height: '100%', overflowY: 'auto' }}
          mode="inline"
          theme={theme}
          inlineCollapsed={collapsed}
          onOpenChange={handleOpenChange}
        >
          <Logo collapsed={collapsed}></Logo>
          {sidebarDom}
        </Menu>
      )
    }
    
    const mapStateToProps = (state) => {
      return {
        router: state.getIn(['light', 'router']),
        theme: state.getIn(['light', 'theme']),
        selectedKeys: state.getIn(['light', 'selectedKeys']),
        collapsed: state.getIn(['light', 'collapsed']),
        userInfo: state.getIn(['light', 'userInfo']).toJS(),
      }
    }
    
    const mapDispatchToProps = (dispatch) => {
      return {
        onSetState(key, value) {
          dispatch({ type: 'SET_LIGHT_STATE', key, value })
        },
        onDispatch(action) {
          dispatch(action)
        },
      }
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Sidebar))
    

    router.js:

    import { lazy } from 'react'
    
    // isDevMenu=true只在开发环境显示
    const router = [
      {
        title: '首页',
        icon: 'home',
        className: 'm-sidebar-home',
        isVisible: true,
        path: '/sale/index/home',
        component: lazy(() => import('../../views/light/index/home/Home'))
      },
      {
        title: 'xx管理',
        icon: 'base',
        isVisible: true,
        key: '/sale/index/offline',
        children: [
          {
            title: 'xx管理',
            icon: '',
            isVisible: true,
            path: '/sale/index/offline/companyList',
            component: lazy(() => import('../../views/sale/index/offline/companyList/Index'))
          },   
          {
            title: 'xx管理',
            icon: '',
            isVisible: true,
            path: '/sale/index/offline/shopList',
            component: lazy(() => import('../../views/sale/index/offline/shopList/Index'))
          },                                            
        ]
      }, 
    ]
    
    
    export default router

  • 相关阅读:
    JavaScript getElementByID() not working
    [转] 从此不再惧怕URI编码:JavaScript及C# URI编码详解
    win 8.1 突然没有了声音 -- 解决办法
    升级打怪第一天 -------字符串重复
    Flex布局
    HTML 的全局事件属性
    CSS position 相对定位和绝对定位
    将1100秒转换为分秒格式
    新手小白的上路之旅
    谈谈我对Manacher算法的理解
  • 原文地址:https://www.cnblogs.com/xutongbao/p/15264341.html
Copyright © 2011-2022 走看看