<>react后台管理系统路由配置:
<>大概需求:
假设:dashboard文件放的是整个页面,分为导航,和侧边栏,中间内容栏;导航和侧边每个路由都需要,将相关的路由页面都放到中间内容共栏就可以。
1、分为两部分大文件、login登入页面,/ 转到到dashboard,
这样分的好处是,不用跳转到一个页面就判断有没有登入。这里进行统一判断,如果没有登入 ,其他以/ 开头的页面都会跳转到login中。
一旦登入后就跳转到dashboard页面中,这个页面有导航栏,和侧边栏,这两个是公用内容,哪里都用的上。下面部分就是动态会变的。
<>一、文件:router.js路由配置
做判断,登入了就允许看所有页面,没有登入就打到登入页面
import React, { Component } from 'react' //引入核心 import { //引入路由相关配置 HashRouter,
// 构建 hash 路由, #/home #/login === ( Vue mode:hash ) // BrowserRouter,// 构建
history 路由 /home /login === ( Vue mode:history ) Redirect, //重定向 Route, //路由坑
Switch//模糊匹配,箱单与Switch判断语句 } from 'react-router-dom' //-------blog
自定义组件------------------------- import Login from '../views/login/Login'
//111、登入页面 import DashBoard from '../views/dashboard/DashBoard'//222、设置为/
的页面,整个页面结构都在这个文件,名字随便取 export default class Router extends Component { render()
{ return ( <HashRouter> //哈希路由 <Switch> //判断路由,先匹配登入页面,匹配上就brack出去 <Route path=
"/login" component={Login}/> 路由拦截--三目
————用render箭头函数形式,做判断,是否有token,有就说明登入,能进入到后台页面,没有就打回登入页面<Route path="/" render={
()=> localStorage.getItem("token")?<DashBoard/>:<Redirect to="/login"/> } /> </
Switch> </HashRouter> ) } }
<>2、配置完成后就直接在App.js中引入,让他加载这个路由页面就可以了
文件:App.js配置使用
import React from 'react'; //引入核心react import BlogRouter from './router'
//引入router路由配置文件 //根组件 class App extends React.Component{ render(){ return <
BlogRouter/> //直接return出去,变成jsx文件供页面使用 } } export default App;
<>3、 dashboard文件用于配置整个页面结构及路由:( 斜杠 / 页面 )
注:真实工作中权限这里不用自己做判断,我们只负责循环操作
//引入相关的路由及核心 import React, { Component } from 'react' import { Route, Redirect,
Switch} from 'react-router-dom' import Home from '../home/Home' import Users
from '../usermanage/Users' import SideMenu from './SideMenu' //组件的侧边栏,用antd-UI搭建
import TopHeader from './TopHeader' //组件的导航栏,用antd-UI搭建 import './index.css'
//antd组件库的配置 import { Layout } from 'antd'; import Create from
'../article-manage/Create' const { Content } = Layout; //解构 export default class
DashBoard extends Component { render() { let { roleType } = JSON.parse(
localStorage.getItem("token")) //将token结构出来 return ( <Layout> {/* 自定义的sidemenu
*/} <SideMenu></SideMenu> //侧边栏 <Layout className="site-layout"> <TopHeader></
TopHeader> //组件导航栏 <Content //以下全是组件内容区的配置, className="site-layout-background"
style={{ margin: '24px 16px', padding: 24, minHeight: 'auto', }} > <Switch>
//开始相关的路由配置 {/* home路由 */} <Route path="/home" component={Home} /> {/*
用户权限-用户列表 */}
//这个判断是根据token的内容,判断登入后用户的权限,如果登入用户权限大于3的话就渲染这个路由组件,如小于,就不渲染,这个用户就没有权限看着列表 {
roleType>= 3 ? <Route path="/user-manage/users" component={Users} /> : null } {
/* 权限管理-权限列表,角色列表 */} { roleType >= 3 ? <Route path="/right-manage" component={
Manage} /> : null } {/* 文章管理- 文章列表 文章分类 */} <Route path="/article-manage/list"
component={List} /> <Route path="/article-manage/preview/:myid" component={
Preview} exact /> //动态组件的详情页面 <Route path="/article-manage/create" component={
Create}/> <Redirect from="/" to="/home" exact /> //重定向到home页面 <Route path="*"
component={NotFound} /> //上面的都匹配不到,设置 “ * ”后随便在地址栏乱输都会匹配404组件 </Switch> </
Content> </Layout> </Layout> ) } }
<>渲染路由的第二种情况:(后端返回的数据直接渲染)
import React, { Component } from 'react' //引入核心 import {Route,Redirect,Switch}
from 'react-router-dom'//引入路由 import newList from '@/views/index' //引入后端数据
import { Layout } from 'antd' //antd const { Content } = Layout;//antd export
default class Contents extends Component { //组件 constructor(props) { super(props
) this.state = { } } forList = (newList) =>{ //定义函数,接收后端数据 //
console.log(newList) return newList.map((item) =>{ //循环 if(item.children) {
//判断是否有孩子,有就继续循环 return item.children.map((item) =>{ //循环孩子数据路由 return <Route
exact key={item.id} path={item.path} component={item.component}></Route> }) }
else{//如果没有孩子就直接循环 return <Route exact key={item.id} path={item.path} component=
{item.component}></Route> } }) } render () { return ( <Content className=
"site-layout-background" style={{ margin: '24px 16px', padding: 24, minHeight:
'100%', }} > <Switch>//保留模糊匹配 {this.forList(newList)}
//调用上面定义的函数,将后端数据传递过去用于渲染路由 <Redirect from="/*" to="/home"></Redirect> //路由重定向 <
/Switch> {/* Content */} </Content> ) } }
<>二、侧边栏配置:(路由跳转)
1、先配置假数据用于做侧边栏的循环:(工作中是后端返回)
list.js文件: const MyData = [ {//一级菜单需要的参数 title:"首页", icon:UserOutlined,
permission:1, //权限判断 path:'/home' //设置的好处:1、可以用来跳转页面,2、可以用来配置下拉菜单的默认下来项 }, {
title:"用户管理", icon:VideoCameraOutlined, permission:3, path:'/user-manage',
children:[ //二级菜单的配置 { title:"用户列表", icon:UserDeleteOutlined , permission:3,
path:"/user-manage/users" } ] }, ] export default MyData //抛出去
配置侧边栏:
用antd-UI框架布局侧边栏
defaultSelectedKeys:组件库提供设置菜单高亮的属性
defaultOpenKeys:组件库提供设置菜单默认展开效果,key需要和后端返回的数据路径一致
注:递归调用时经典
import React, { Component } from 'react' //引入react核心 import MenuArr from
'../../router/list.js'//引入上面定义的假数据 import { Layout, Menu } from 'antd'; import {
withRouter} from 'react-router'; //引入高阶组件 import {connect} from 'react-redux'
//引入react-redux const { Sider } = Layout; //解构 const { SubMenu } = Menu; class
SideMenu extends Component { //组件 state = { collapsed: false }
//1、自己封装渲染函数,遍历侧边栏 renderMenu = (menus)=>{ //BBB let {roleType} = JSON.parse(
localStorage.getItem("token")) //2、roleType
当前登录用户的roleType(就是用户权限,从token中拿出来做判断,权限越高看的越多 return menus.map(item=>{
//3、提示:判断当前登录的用户的角色值(roleType),跟当前要渲染的侧边栏项需要的角色值进行对比 if(item.children &&
roleType>= item.permission){
//4、判断是否有孩子参数,有就渲染二级标题,并且判断登入用户的权限是不是大于标题数据的权限,大于就渲染,小于就隐藏(就是数据中定义的permission)
return <SubMenu key={item.path} title={
//重:将每个渲染的标题都设置key(就是数据中定义的path="/home")用于做编程试导航和菜单高亮 <span> <item.icon/> <span>
{item.title}</span> </span> }> { //递归用法 this.renderMenu(item.children)
//重:7、下面还有children在继续递归渲染,(就不需要每次都去做循环渲染) } </SubMenu> }else{ if( item.
permission> roleType){ //6、判断登入的权限是否大于当前标题数据的权限,大于就显示,小于就隐藏。 return null }
return ( //5、如果没有children孩子数据,就直接渲染一级标题,menu <Menu.Item key={item.path} icon={<
item.icon />}>重:将每个渲染的标题都设置key(就是数据中定义的path="/home")用于做编程试导航和菜单高亮 {item.title} <
/Menu.Item> ) } }) } handleChangePage = (obj)=>{ //AAA // console.log(obj) //
高阶组件提供 this.props.history.push(obj.key)//key路由对应的路径,进行点击每一个标题的时候,条状到响应的路由去 }
render() { // console.log(this.props) //拿到此时路径 let selectedKey = this.props.
location.pathname //设置defaultSelectedKeys let openKey = "/"+this.props.location.
pathname.split("/")[1] //截取二级路由的一级路径,设置defaultOpenKeys return ( <Sider trigger={
null} collapsible collapsed={this.props.isCollapsed}> {/* <div className="logo"
/> */} { /* andt组件库提供:defaultSelectedKeys :高亮显示谁?//从编程试导航中结构出来path来,给到这个属性
defaultOpenKeys://初始展开的 SubMenu 菜单项 key 数组
(前提是渲染标题的时候,key要和解构出来的path相对应,不然初始化展开不起作用) */ } <Menu theme="dark" mode="inline"
defaultSelectedKeys={[selectedKey]} defaultOpenKeys={[openKey]} onClick ={this.
handleChangePage} //AAA //点击 MenuItem 调用此函数,会传递点击的是具体的哪一个值过去,就包含数据的path > {
//BBBB this.renderMenu(MenuArr) //调用上面抽离的函数,渲染侧边栏,传递的值就是引入的假数据 } </Menu> </Sider
> ) } } // connec拿到了store, store.getState() const mapStateToProps = state => {
// console.log(state) return { name:"kerwin", a:1, isCollapsed:state.isCollapsed
} //函数返回值 ,就是将来往sideMeun 组件传来的属性 }// 映射redux 状态==>当前组件属性 export default connect(
mapStateToProps)(withRouter(SideMenu))