目录
一、React-Router知识回顾
二、路由鉴权应用分析
三、路由鉴权配置
四、权限控制
一、React-Router知识回顾
React-router相关的文章中我已经给大家演示了最基础的应用:
<Switch >
<Route path="/products/:id" component={ProductDetails} />
<Redirect from="/mall" to="/products" />
<Route path="/products" render={( props ) => <Products groupId="99" {...props} />} />
<Route path="/posts/:year?/:month?" component={Posts} />
<Route path="/admin" component={Dashboard} />
<Route path="/not-found" component={NotFound} />
<Route path="/" exact component={Home} />
<Redirect to="/not-found" />
</Switch>
<Switch>: 渲染与该地址匹配的第一个子节点 或者
<Route>: 是用于声明路由映射到应用程序的组件层
<Redirect>: 在应用中可以设置重定向到其他 route,默认要设置to(目标),可以设置from(从哪个路由)
< Link>: 允许用户浏览应用的主要方式。会去渲染一个可访问的锚标签。<NavLink>: 一个特殊版本的 Link,当它与当前 URL 匹配时,为其渲染元素添加样式属性。
<Router>: Router 是所有路由组件共用的底层接口。通常,我们的应用程序将使用其中一个高级路由器代替:
<BroswerRouter>或<HashRouter>,使用Router将组件包装起来,保持UI和URL的同步
<BrowserRouter>
<App />
</BrowserRouter>
二、路由鉴权应用分析
可以画一个简单的图,将页面、路由、权限做一个整理
所以我们可以将路由分为:
一层路由: /、/login、/not-found、/backend
二层路由:/backend/product、/backend/users、/backend/admin
根据需要的页面我们可以搭建出管理应用的工程目录结构出来,大致的结构可以是这样设计的
三、路由鉴权配置
首先我们创建一个配置js文件,用于存放之前我们分析的两种路由配置,另外由于管理后台的菜单路由也是关联的,也同时要创建一个导航的配置
import Home from "../components/home";
...
/* 第一层路由 */
const routes = [
{
path: "/",
exact: true,
component: Home,
},
{
path: "/login",
component: Login,
},
{
path: "/backend",
component: MyLayout,
},
{
path: "/not-found",
component: NotFound,
},
];
/* 第二层路由 */
const componentsRoutes = [
{
key: "backend",
path: "/backend",
exact: true,
component: Backend,
},
{
key: "product",
path: "/backend/product",
component: Product,
},
{
key: "users",
path: "/backend/users",
component: Users,
},
{
key: "admin",
path: "/backend/admin",
component: Admin,
},
];
/* 菜单导航 */
const navi = [
{
title: "课程",
key: "product",
path: "/backend/product",
},
{
title: "用户",
key: "users",
path: "/backend/users",
},
{
title: "后台",
key: "admin",
path: "/backend/admin",
},
];
export { routes, componentsRoutes, navi };
关于配置的属性值其实就是React-router所需要的传入参数,包括key,path,exact,component,而导航是配置了三个属性:title(导航名称),key和对应的path
有了配置之后,就需要把配置在组件内做渲染,这时就需要定义一个通用的函数,它的输入就是上面的配置对象,而输入则是React-router组件
import React from "react";
import { Route, Switch, Redirect } from "react-router-dom";
const renderRoutes = (routes, switchProps = {}) => {
return (
<Switch {...switchProps}>
{routes.map((route, i) => (
<Route
key={route.key || i}
path={route.path}
exact={route.exact}
strict={route.strict}
render={(props) => (
<route.component {...props} {...route.extraProps} route={route} />
)}
/>
))}
<Redirect to="/not-found" />
</Switch>
);
};
export default renderRoutes;
定义了方法之后,就可以做路由的配置了,我们首先在App组件中做第一层的路由配置
<div className="App">
{renderRoutes(routes)}
</div>
对于管理后台中的路由加载,我们需要在layout的组件中去做第二层的路由配置,首先我们来渲染左侧的导航菜单
//定义导航渲染函数
renderMenu = () =>{
return navi.map(item => {
return <MenuItem key={item.key}><NavLink to={item.path}>{item.title}</NavLink></MenuItem>
})
}
//在menu中渲染
<Menu>
{this.renderMenu()}
</Menu>
和渲染第一层的路哟一样,我们再将第二层定义的路由对象componentsRoutes使用renderRoutes方法渲染到页面上。这样我们的路由配置部分就完成了
四、权限控制
一般来说权限的处理方法:
无权限重定向: 可以定向到登录或提示页面
无权限提示: 提示没有权限查看页面
无权限隐藏: 直接隐藏无权限项
做权限控制的思路也很简单,先设置每个页面或组件的对应角色权限,然后判断当前用户角色是否符合,来决定要不要做路由渲染
有了这样的思路,我们就先来对路由配置文件添加permission属性,来控制每个页面和组件的权限
import Home from "../components/home";
...
const routes = [
{
path: "/",
exact: true,
component: Home,
permission: [1,2,3]
},
{
path: "/login",
component: Login,
permission: [1,2,3]
},
{
path: "/backend",
component: MyLayout,
permission: [2,3]
},
{
path: "/not-found",
component: NotFound,
permission: [1,2,3]
},
];
const componentsRoutes = [
{
key: "backend",
path: "/backend",
exact: true,
component: Backend,
permission: [2,3]
},
{
key: "product",
path: "/backend/product",
component: Product,
permission: [2,3]
},
{
key: "users",
path: "/backend/users",
component: Users,
permission: [2,3]
},
{
key: "admin",
path: "/backend/admin",
component: Admin,
permission: [3]
},
];
const navi = [
{
title: "课程",
key: "product",
path: "/backend/product",
permission: [2,3]
},
{
title: "用户",
key: "users",
path: "/backend/users",
permission: [2,3]
},
{
title: "后台",
key: "admin",
path: "/backend/admin",
permission: [3]
},
];
export { routes, componentsRoutes, navi };
接着思路,接下来就要是将renderRoutes这个方法做一些改变
import React from "react";
import { Route, Switch, Redirect } from "react-router-dom";
const auth = window.user.data
const renderRoutes = (routes, switchProps = {}) => {
let routers = []
routes.forEach( (route, i) => {
if(route.permission.indexOf(auth) >= 0){
routers.push(
<Route
key={route.key || i}
path={route.path}
exact={route.exact}
strict={route.strict}
render={(props) => (
<route.component {...props} {...route.extraProps} route={route} />
)}
/>
)
}else{
routers.push(
<Redirect key={route.key || i} from={route.path} to="/login" />
)
}
});
return (
<Switch {...switchProps}>
{routers}
<Redirect to="/not-found" />
</Switch>
);
};
export default renderRoutes;
接下来设置一下导航,将导航设置为无权限隐藏,当没有权限的时候,就不渲染相关的菜单即可
renderMenu = () =>{
return navi.map(item => {
return item.permission.indexOf(auth) >=0 ?
<MenuItem key={item.key}><NavLink to={item.path}>{item.title}</NavLink></MenuItem> : null;
})
}
最后我们需要设置一下首页的按钮,根据不同的权限去定向不同的页面就可以了
handleEnter = () => {
if(auth === 1){
window.location.href = "/login"
}else{
window.location.href = "/backend"
}
}
render() {
return (
<div className="home">
<Button onClick={this.handleEnter} className="enter-btn" type="primary" size="large" >点击进入</Button>
</div>
);
}