ReactAntd(六) ANTD 导航第四种情况

效果图

鼠标点击按钮 能收缩到只剩下图标

前期准备

自定义路由图标

(1) 安装包依赖


npm install --save @ant-design/icons

(2) 构建基类

  • 在 components 文件下面新建一个文件夹名字起名 Common,在 Common 里面在新建一个文件夹起名 Iconfont

  • 在 iconfont 文件夹 下面新建一个 iconfont.js 文件

import { createFromIconfontCN } from '@ant-design/icons'

const MyIcon = createFromIconfontCN({
  scriptUrl: '//at.alicdn.com/t/font_1962285_oiwjxokadzm.js',
})

export default MyIcon

// scriptUrl 就是你在阿里图标库最后生成的地址

-

(3) 使用的时候

import MyIcon from '../Iconfont/Iconfont'

//使用的时候就用如下即可 type里面的就是图标名称
//<MyIcon type="icon-Newuserzone"></MyIcon>

开始使用路由

(1) 在 public 文件下新建一个文件夹 api

  • 在 api 里面新建一个 menu.json 文件
;[
  {
    title: '首页',
    key: '/admin/home',
    icon: 'icon-gift',
  },
  {
    title: 'UI',
    key: '/admin/ui',
    icon: 'icon-hot',
    children: [
      {
        title: '按钮',
        key: '/admin/ui/buttons',
        icon: 'icon-Newuserzone',
      },
      {
        title: '弹框',
        key: '/admin/ui/modals',
        icon: 'icon-Newuserzone',
      },
      {
        title: 'Loading',
        key: '/admin/ui/loadings',
        icon: 'icon-Newuserzone',
      },
      {
        title: '通知提醒',
        key: '/admin/ui/notification',
        icon: 'icon-Newuserzone',
      },
      {
        title: '全局Message',
        key: '/admin/ui/messages',
        icon: 'icon-Newuserzone',
      },
      {
        title: 'Tab页签',
        key: '/admin/ui/tabs',
        icon: 'icon-Newuserzone',
      },
      {
        title: '瀑布流',
        key: '/admin/ui/gallery',
        icon: 'icon-Newuserzone',
      },
      {
        title: '轮播图',
        key: '/admin/ui/carousel',
        icon: 'icon-Newuserzone',
      },
    ],
  },
  {
    title: '表单',
    key: '/admin/form',
    icon: 'icon-form',
    children: [
      {
        title: '登录',
        key: '/admin/form/login',
        icon: 'icon-packaging',
      },
      {
        title: '注册',
        key: '/admin/form/reg',
        icon: 'icon-packaging',
      },
    ],
  },
  {
    title: '表格',
    key: '/admin/table',
    icon: 'icon-security',
    children: [
      {
        title: '基础表格',
        key: '/admin/table/basic',
        icon: 'icon-hot',
      },
      {
        title: '高级表格',
        key: '/admin/table/high',
        icon: 'icon-hot',
      },
    ],
  },
  {
    title: '富文本',
    key: '/admin/rich',
    icon: 'icon-set',
  },
  {
    title: '城市管理',
    key: '/admin/city',
    icon: 'icon-map',
  },
  {
    title: '订单管理',
    key: '/admin/order',
    icon: 'icon-integral',
    btnList: [
      {
        title: '订单详情',
        key: '/admin/order/detail',
        icon: 'icon-hot',
      },
      {
        title: '结束订单',
        key: '/admin/order/finish',
        icon: 'icon-hot',
      },
    ],
  },
  {
    title: '员工管理',
    key: '/admin/usermanage',
    icon: 'icon-usercenter',
  },
  {
    title: '车辆地图',
    key: '/admin/bikeMap',
    icon: 'icon-map',
  },
  {
    title: '图表',
    key: '/admin/charts',
    icon: 'icon-map',
    children: [
      {
        title: '柱形图',
        key: '/admin/charts/bar',
        icon: 'icon-certified-supplier',
      },
      {
        title: '饼图',
        key: '/admin/charts/pie',
        icon: 'icon-certified-supplier',
      },
      {
        title: '折线图',
        key: '/admin/charts/line',
        icon: 'icon-certified-supplier',
      },
    ],
  },
  {
    title: '权限设置',
    key: '/admin/permission',
    icon: 'icon-usercenter',
  },
]

组件里面写

(1) 第一步把最外层的组件 colspan 编程 redux 里面的数据纯动态

  • 在 admin.js 里面写
import React, { Component, Fragment } from 'react'
import Header from '../components/Common/Header/Header'
import Footer from '../components/Common/Footer/Footer'
import LeftNav from '../components/Common/Left4/Left4'
import { Row, Col } from 'antd'
import { connect } from 'react-redux'
class Admin extends Component {
  constructor(props) {
    super(props)
    this.state = {
      message: 'admin页面',
    }
  }
  componentDidMount() {
    console.log(this.content)
  }
  render() {
    const { menuColSpan } = this.props
    return (
      <Fragment>
        <Row>
          <Col span={menuColSpan.left}>
            <LeftNav></LeftNav>
          </Col>
          <Col span={menuColSpan.right}>
            <Header></Header>
            {this.props.children}
            <Footer></Footer>
          </Col>
        </Row>
      </Fragment>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    menuColSpan: state.menuColSpan,
  }
}
const mapDispatchToProps = (dispatch) => {
  return {}
}
//最后利用store挂钩

export default connect(
  mapStateToProps, //这里面放的是数据
  mapDispatchToProps //里面放的是操作的数据的方法
)(Admin)

(2)reducer.js 里面默认值

import {
  CHANGE_VALUE,
  CLICK_CHANGE,
  DELETE_ITEM,
  CHANGE_LOADING,
  CHANGE_MENUCOLSPAN,
} from './actiontypes'

const defaultState = {
  inputValue: '123',
  list: [
    'Racing car sprays burning fuel into crowd.',
    'Japanese princess to wed commoner.',
    'Australian walks 100km after outback crash.',
    'Man charged over missing wedding girl.',
    'Los Angeles battles huge wildfires.',
  ],
  //必须要用的
  loadingFlag: false,
  menuColSpan: { left: 2, right: 22 },
}
export default (state = defaultState, action) => {
  //这里判断action的type然后在返回state
  if (action.type === CHANGE_VALUE) {
    let newresult = JSON.parse(JSON.stringify(state)) //必须要重新生成一个新的对象,也不能使用Object.asign这样有的时候不起作用,而且每个判断里面必须有返回值
    newresult.inputValue = action.value
    return newresult
  }
  if (action.type === CLICK_CHANGE) {
    let newData = JSON.parse(JSON.stringify(state))
    if (newData.inputValue != null) {
      newData.list.push(newData.inputValue)
      newData.inputValue = ''
    }
    return newData
  }
  // 这里就是删除方法,必须返回新数据
  if (action.type === DELETE_ITEM) {
    let newData = JSON.parse(JSON.stringify(state))
    newData.list.splice(action.value, 1)
    return newData
  }
  //----------正式开始------------
  if (action.type === CHANGE_LOADING) {
    let newData = JSON.parse(JSON.stringify(state))
    newData.loadingFlag = action.value
    return newData
  }
  if (action.type === CHANGE_MENUCOLSPAN) {
    let newData = JSON.parse(JSON.stringify(state))
    newData.menuColSpan = action.value
    return newData
  }
  return state
}

这样核心思想就是点击收缩按钮,发送走数据。改变 redux 里面的值,这样 colspan 就会自动变化

(3)路由组件里面写

import React, { Component } from 'react'
import { Menu, Button } from 'antd'
import http from '../../../api/request'
import MyIcon from '../Iconfont/Iconfont'
import { connect } from 'react-redux'
//收缩按钮的图标
import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons'
//加载样式
import './Menu.less'
//发送走收缩的条件
import { ACTION_CHANGE_MENUCOLSPAN } from '../../../store/actioncreaters'
const { SubMenu } = Menu

class LeftComponent extends Component {
  constructor(props) {
    super(props)
    this.state = {
      message: '导航',
      menuList: [],
      collapsed: false,
      defaultSelectedKeys: ['/admin/ui/buttons'],
      defaultOpenKeys: ['/admin/ui'],
    }
    this.toggleCollapsed = this.toggleCollapsed.bind(this)
    this.handleClick = this.handleClick.bind(this)
  }
  componentDidMount() {
    this.getMenuList()
  }

  render() {
    return (
      <div style={{ width: '100%' }}>
        <Button
          type="primary"
          onClick={this.toggleCollapsed}
          style={{
            margin: '0 auto',
            marginBottom: 16,
            marginTop: 20,
            display: 'block',
          }}
        >
          {React.createElement(
            this.state.collapsed ? MenuUnfoldOutlined : MenuFoldOutlined
          )}
        </Button>
        <Menu
          defaultSelectedKeys={this.state.defaultSelectedKeys}
          defaultOpenKeys={this.state.defaultOpenKeys}
          mode="inline"
          inlineCollapsed={this.state.collapsed}
          style={{ width: '100%', background: '#001529', color: '#ccc' }}
          onClick={this.handleClick}
        >
          {this.state.menuList.map((content, index) => {
            if (content.children) {
              return (
                <SubMenu
                  title={content.title}
                  key={content.key}
                  icon={<MyIcon type={content.icon}></MyIcon>}
                >
                  {content.children.map((item, index2) => {
                    return (
                      <Menu.Item
                        key={item.key}
                        icon={<MyIcon type={item.icon}></MyIcon>}
                      >
                        {item.title}
                      </Menu.Item>
                    )
                  })}
                </SubMenu>
              )
            } else {
              return (
                <Menu.Item
                  key={content.key}
                  icon={<MyIcon type={content.icon}></MyIcon>}
                >
                  {content.title}
                </Menu.Item>
              )
            }
          })}
        </Menu>
      </div>
    )
  }
  toggleCollapsed() {
    this.setState(
      {
        collapsed: !this.state.collapsed,
      },
      function () {
        this.props.handleCollapsed(this.state.collapsed)
      }
    )
  }
  getMenuList() {
    let _this = this
    http.get('/api/menu.json').then((res) => {
      _this.setState({
        menuList: res.data,
      })
    })
  }
  handleClick(e) {
    console.log(e)
  }
}

const mapStateToProps = (state) => {
  return {}
}
const mapDispatchToProps = (dispatch) => {
  return {
    handleCollapsed(flag) {
      if (flag) {
        //true 就是收缩
        let value = { left: 1, right: 23 }
        const action_result = ACTION_CHANGE_MENUCOLSPAN(value)
        dispatch(action_result)
      } else {
        //false 就是展开
        let value = { left: 2, right: 22 }
        const action_result = ACTION_CHANGE_MENUCOLSPAN(value)
        dispatch(action_result)
      }
    },
  }
}

//最后利用store挂钩

export default connect(
  mapStateToProps, //这里面放的是数据
  mapDispatchToProps //里面放的是操作的数据的方法
)(LeftComponent)

(4) menu.css(这里要特别注意以后修改在这里)

.ant-menu-submenu-popup > .ant-menu {
  background: #001529;
  color: white;
  box-shadow: none;
}

.ant-menu-item:hover,
.ant-menu-item-active,
.ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,
.ant-menu-submenu-active,
.ant-menu-submenu-title:hover {
  color: #ffe493;
}

.ant-menu-item {
  .anticon {
    font-size: 20px !important;
    //改变图标位置依据情况
    vertical-align: -0.25em;
  }
}

.ant-menu-submenu-title {
  .anticon {
    font-size: 20px !important;
    //改变图标位置依据情况
    vertical-align: -0.25em;
  }
}

// 点击以后改变颜色
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
  background: none;
  color: #ffe493;
}

.ant-menu-submenu-selected {
  color: #ffe493 !important;
}

//改变第二种颜色
.ant-menu-submenu {
  .ant-menu {
    background: #001529;
    color: white;
    box-shadow: none;
  }
}

// 改变小三角

.ant-menu-submenu-arrow:before,
.ant-menu-submenu-arrow:after {
  background-image: linear-gradient(
    to right,
    rgba(255, 255, 255, 1),
    rgba(255, 255, 255, 1)
  ) !important;
}

//鼠标放上去

.ant-menu-submenu-active {
  .ant-menu-submenu-arrow:before {
    background-image: #ffe493;
  }
}

.ant-menu-submenu-active {
  .ant-menu-submenu-arrow:after {
    background-image: #ffe493;
  }
}

//收缩按钮颜色
.ant-btn-primary {
  background: #001529;
  border: 1px solid white;
}

.ant-btn-primary:hover,
.ant-btn-primary:focus {
  background: #ffe493;
  color: #001529;
}

//去掉1PX

.ant-menu-inline,
.ant-menu-vertical,
.ant-menu-vertical-left {
  border-right: none;
}

//去掉padding-left

.ant-menu-inline-collapsed > .ant-menu-item,
.ant-menu-inline-collapsed
  > .ant-menu-item-group
  > .ant-menu-item-group-list
  > .ant-menu-item,
.ant-menu-inline-collapsed
  > .ant-menu-item-group
  > .ant-menu-item-group-list
  > .ant-menu-submenu
  > .ant-menu-submenu-title,
.ant-menu-inline-collapsed > .ant-menu-submenu > .ant-menu-submenu-title {
  padding-left: 0px !important;
  margin: 0 auto;
  width: 100%;
}

.ant-menu-item {
  padding-left: 14px !important;
  margin: 0 auto;
  width: 100%;
}

.ant-menu-submenu-title {
  padding-left: 14px !important;
  margin: 0 auto;
  width: 100%;
}

//子元素里面的padding 比如按钮,轮播图之类的
.ant-menu-sub {
  .ant-menu-item {
    padding-left: 24px !important;
    margin: 0 auto;
    width: 100%;
  }
}

//改变收缩后图标的位置

.ant-menu-inline-collapsed > .ant-menu-item .anticon,
.ant-menu-inline-collapsed
  > .ant-menu-item-group
  > .ant-menu-item-group-list
  > .ant-menu-item
  .anticon,
.ant-menu-inline-collapsed
  > .ant-menu-item-group
  > .ant-menu-item-group-list
  > .ant-menu-submenu
  > .ant-menu-submenu-title
  .anticon,
.ant-menu-inline-collapsed
  > .ant-menu-submenu
  > .ant-menu-submenu-title
  .anticon {
  margin-left: 50%;
}

文章作者: 雾烟云
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 雾烟云 !
  目录