前言

一如既往,实战出真理.

有兴趣的可以瞧瞧,没兴趣的大佬请止步于此.

免得浪费您的时间


效果图

  • 基于antdsidebar组件封装

折腾记的技术栈选型

  • Mobx & mobx-react(用起来感觉良好的状态管理器)
  • React 16.4.2 (从这个起步,用新不用旧)
  • React Router V4 (如上)
  • antd (版本追求如上 , 阿里出品的UI框架)
  • styled-components (不想写单独的样式文件,用这个是棒棒的,用过都说好)
  • webpack 4.16.5(版本追求如上)

实现思路

实现思路

  • 自行维护一份静态路由表
  • 结合路由的history对象的pathanme
  • 在组件渲染完毕的情况下,再去遍历路由表,通过setState重新渲染侧边栏
  • 为什么不在组件初始化的时候就设置,那这样对于404的路由没法控制
    • react-router-dom v4虽然提供了全局404组件,但是history里面没有代表404的状态

实现目标

  • 点击侧边栏的子菜单会改变标题,对应的item也会高亮
  • 直接修改路由,初次加载等会自动展开对应的分组,高亮对应的子项
  • 不匹配的路由不展开和高亮任何

能学到啥

我尽量注释,而收获见仁见智了

我的思路? 我的的代码姿势? 仅供参考


实现代码

基础版

  • 静态路由表一份
export const sidebarData = [{key: 'group0',title: {icon: 'dashboard',text: '数据分析'},children: [{key: '1',text: '数据监控',path: '/dashboard/monitor'},{key: '2',text: '数据分析',path: '/dashboard/analyze'}]},{key: 'group1',title: {icon: 'play-circle',text: '音频管理'},children: [{key: '6',text: '声兮列表',path: '/voice/sxlist'},{key: '7',text: '回声列表',path: '/voice/calllist'}]},{key: 'group2',title: {icon: 'schedule',text: '活动中心'},children: [{key: '11',text: '活动列表',path: '/active/list'},{key: '12',text: '新建活动',path: '/active/add'}]},{key: 'group3',title: {icon: 'apple-o',text: 'APP管理'},children: [{key: '16',text: '移动交互',path: '/appmanage/interaction'},{key: '17',text: '回声列表',path: '/test'},{key: '18',text: '用户列表',path: '/user/list'}]},{key: 'group4',title: {icon: 'safety',text: '安全中心'},children: [{key: '21',text: '举报处理',path: '/safety/report'},{key: '22',text: '广播中心',path: '/safety/broadcast'}]},{key: 'group5',title: {icon: 'user',text: '系统设置'},children: [{key: '26',text: '个人设置',path: '/user/setting'},{key: '27',text: '用户列表',path: '/user/list'}]},{key: 'group6',title: {icon: 'info-circle',text: '平台设置'},children: [{key: '31',text: '用户协议',path: '/platform/license'},{key: '32',text: '帮助中心',path: '/platform/help'}]}];export const groupKey = sidebarData.map(item=>item.key);复制代码
  • sidebar

import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';// antd
import { Layout, Menu, Icon } from 'antd';
const { Sider } = Layout;
const { SubMenu, Item } = Menu;
import { sidebarData, groupKey } from 'pages/Layout/SidebarData';// Logo组件
import Logo from 'pages/Layout/Logo';
@withRouter
class Sidebar extends Component {constructor(props) {super(props);// 初始化置空可以在遍历不到的时候应用默认值this.state = {openKeys: [''],selectedKeys: [''],rootSubmenuKeys: groupKey,itemName: ''};}setDefaultActiveItem = ({ location }) => {const { pathname } = location;sidebarData.map(item => {if (item.pathname) {// 做一些事情,这里只有二级菜单}// 因为菜单只有二级,简单的做个遍历就可以了if (item.children && item.children.length > 0) {item.children.map(childitem => {// 为什么要用match是因为 url有可能带参数等,全等就不可以了// 若是match不到会返回nullif (pathname.match(childitem.path)) {this.setState({openKeys: [item.key],selectedKeys: [childitem.key]});// 设置titledocument.title = childitem.text;}});}});};componentDidMount = () => {// 设置菜单的默认值this.setDefaultActiveItem(this.props);};OpenChange = openKeys => {console.log(openKeys);const latestOpenKey = openKeys.find(key => this.state.openKeys.indexOf(key) === -1);console.log(latestOpenKey);if (this.state.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {this.setState({ openKeys });} else {this.setState({openKeys: latestOpenKey ? [latestOpenKey] : [...openKeys]});}};render() {const { openKeys, selectedKeys } = this.state;const { collapsed, onCollapse } = this.props;const SideTree = sidebarData.map(item => (<SubMenukey={item.key}title={<span><Icon type={item.title.icon} /><span>{item.title.text}</span></span>}>{item.children &&item.children.map(menuItem => (<Itemkey={menuItem.key}onClick={() => {// 设置高亮的itemthis.setState({ selectedKeys: [menuItem.key] });// 设置文档标题document.title = menuItem.text;}}><Link to={menuItem.path}>{menuItem.text}</Link></Item>))}</SubMenu>));return (<Sidercollapsiblebreakpoint="lg"collapsed={collapsed}onCollapse={onCollapse}trigger={collapsed}><Logo collapsed={collapsed} /><MenusubMenuOpenDelay={0.3}theme="dark"openKeys={openKeys}selectedKeys={selectedKeys}mode="inline"onOpenChange={this.OpenChange}>{SideTree}</Menu></Sider>);}
}export default Sidebar;复制代码

collapsed,onCollapse这些是控制侧边栏缩小的,接受的是外部的props


拓展版思路

举一反三,同样我们同在可以在静态路由添加鉴权,比如某个路由仅限某些用户访问!

这样鉴权机制可以做到很细致化,但是对应的判断逻辑也会多起来,看业务改了

也可以维护过渡效果,添加对应的字段,然后每次访问不同URL的时候更改过渡效果

以上的都需要依赖状态管理器,来维护,因为涉及到不同组件的通讯,mobx也可以,redux也行...萝卜青菜各有所爱


答疑

  • 小伙伴留言说要看我的目录如何构建的,其实和常规的搭建差不多,如下

如何生成漂亮的目录树

alias gdtree="tree -I 'node_modules|dist|.git|.vscode|.DS_Store|.idea' -L 2 -a"

我直接写到环境文件里了, -L就是遍历的层级, -a是所有文件(包括隐藏), -I是正则忽略

├── .babelrc  # babel配置
├── .browserslistrc #浏览器的兼容范围
├── .editorconfig # 基础规范
├── .eslintignore # eslint忽略
├── .eslintrc # eslint 配置
├── .gitignore
├── .postcssrc.js # postcss配置
├── .prettierrc # 格式化代码的配置文件
├── README.md
├── build  # webpack的构建目录
│   ├── webpack.base.config.js # 通用的webpack配置,可以理解为common,开发和生产都依赖,比如插件等
│   ├── webpack.development.js  # 开发模式专有,热更新,反向代理啥的
│   └── webpack.production.js # 尽可能的压缩切割,抽离样式为CSS文件什么的
├── jsconfig.json # 用来映射webpack alias 的,这样vscode下才能智能提示alias的路径
├── package.json
├── public
│   ├── favicon.png
│   └── index.html
├── src
│   ├── App.css
│   ├── App.js # 根组件
│   ├── PrivateRoute.js # 私有路由,对Route的封装
│   ├── assets # 静态资源
│   ├── components # 通用组件
│   ├── index.js # webpack的主入口
│   ├── pages # 页面组件
│   ├── services # api的封装,以及汇总地方
│   ├── store # 状态管理
│   └── utils # 公用的代码片段,比如一些函数什么的
├── tests # 存放jest单元测试的目录
│   └── union
└── yarn.lock复制代码

总结

公司最近打算重构整个后台管理系统;把老的两个系统整合在一起....emmm,

单打独斗的好处(bei shang)就是技术选型可以自己把握

说做就做,用最新的webpack4 搭了个架子,开始折腾(因为比较新,更新依赖很容易出问题)....

等项目完毕再把脚手架放出来,估计webpack5都出来了..

有人肯定会说,官方有现成的antd pro为嘛不用..我看了跟dva高度结合,不喜欢,那就自己搭架子

之前用vueng都是整个系统布局自己写一遍...这次试试用现成的侧边栏来实现

有不对之处请留言,看到会及时修正,谢谢阅读.

React 折腾记 - (1) React Router V4 和antd侧边栏的正确关联及动态title的实现相关推荐

  1. React 16.x折腾记 - (1) React Router V4 和antd侧边栏的正确关联及动态title的实现

    前言 一如既往,实战出真理,有兴趣的可以瞧瞧,没兴趣的大佬请止步于此. 效果图 基于antd的sidebar组件封装 折腾记的技术栈选型 Mobx & mobx-react(用起来感觉良好的状 ...

  2. React 折腾记 - (4) 侧边栏联动Tabs菜单-增强版(结合Mobx)

    前言 有小伙伴留言有前进后退没法联动的问题.我仔细梳理下了. 简化了代码逻辑和代码量,重写了一遍,执行逻辑和上个版本有所差异; 上个版本 :React 折腾记 - (3) 结合Mobx实现一个比较靠谱 ...

  3. hitchhiker部署_Hitchhiker的React Router v4指南:无限远的递归路径!

    hitchhiker部署 Welcome to the third part of the Hitchhiker's Guide to React Router v4. In this article ...

  4. [React Router v4] Intercept Route Changes

    If a user has entered some input, or the current Route is in a "dirty" state and we want t ...

  5. [React Router v4] Conditionally Render a Route with the Switch Component

    We often want to render a Route conditionally within our application. In React Router v4, the Route ...

  6. hitchhiker部署_《 Hitchhiker的React Router v4指南》:路由配置的隐藏值

    hitchhiker部署 Welcome to the Hitchhiker's Guide to React Router v4, Part IV! 欢迎来到< React Router v4 ...

  7. 关于React Router v4的虚张声势指南

    In this article, we'll cover the important things you can quickly learn to be informed and confident ...

  8. 使用React Router v4的嵌套路由

    React Router v4 introduced a new declarative, component based approach to routing. With that approac ...

  9. react router v4 简介

    最近使用react router 遇到一个问题:当对某个路由添加参数的时候/list/:app 这列路由,点击这个路由以后再点击其他路由,location地址就追加到后面,问不是replace. /l ...

最新文章

  1. 某程序员遭遇奇葩事:辞退自己的leader竟然命令自己回前公司,给前同事讲代码!...
  2. 概率分布--------离散概率分布和连续概率分布
  3. TextureView+MediaPlayer实现在线短视频播放
  4. java file源码_java File源码理解,探索File路径
  5. 安装linux6.10 I386系统教程,一看就懂的Centos6.10安装教程
  6. php异步轮询如何实现,深入剖析JavaScript异步之事件轮询
  7. 开发人员不得不知的MySQL索引和查询优化
  8. SCCM 2012 R2 从入门到精通 Part11 系统推送(2)
  9. M1 Mac 档案的临时暂存区工具: Yoink
  10. “蓝桥杯”练习系统练习题答案(自己做的)
  11. 5%和1%精度的贴片电阻标称阻值表
  12. windows 技巧篇-解除共享文件夹占用方法,解决共享文件被占用导致不可修改问题,查看共享文件被谁占用方法
  13. CREO:CREO软件之零件【渲染】之对三维零件实现渲染图文教程之详细攻略
  14. Arista携手思科、瞻博网络 计划打造面向云的交换与路由设备
  15. 如何在命令行打开mysql
  16. 蓝桥杯 填写乘法算式
  17. OSChina 周三乱弹 ——学哪种编程语言能保住一头秀发?
  18. 高通Android随身WIFI屏蔽商家远程控制断网
  19. 网络地址192.168.10.0;子网掩码255.255.255.128 计算
  20. OCP-1Z0-053-200题-168题-528

热门文章

  1. extjs 月份选择控件_Ext JS 4实现带week(星期)的日期选择控件(实战二)
  2. 序列每天从0开始_序列化、反序列化原理和Protobuf实现机制
  3. 【grpc】[Python] A file with this name is already in the pool
  4. linux有名管道大小,Linux中的pipe与named pipe(FIFO),即管道和命名管道
  5. ubuntu命令行语法_Linux中重定向命令行的总结(ubuntu学习第三讲)
  6. Gatling性能测试(一)
  7. 这些面试细节90%的人都没注意!怪不得简历白投了...
  8. Matlab与MySQL数据库交互基本操作
  9. mysql 性能问题_mysql 性能问题
  10. php查询对象是否有某个属性可用,JavaScript 判断对象中是否有某属性的常用方法...