import { renderRoutes } from 'react-router-config' import routes from './router.js' const App = () => ( <main> <Switch> {renderRoutes(routes)} </Switch> </main> ) export default App
用过vue的小朋友都知道,vue的router.js 里面添加 meta: { requiresAuth: true }
然后利用 导航守卫
router.beforeEach((to, from, next) => { // 在每次路由进入之前判断requiresAuth的值,如果是true的话呢就先判断是否已登陆 })
2、基于类似vue的路由鉴权想法,我们稍稍改造一下react-router-config
// utils/renderRoutes.js
import React from 'react' import { Route, Redirect, Switch } from 'react-router-dom' const renderRoutes = (routes, authed, authPath = '/login', extraProps = {}, switchProps = {}) => routes ? ( <Switch {...switchProps}> {routes.map((route, i) => ( <Route key={route.key || i} path={route.path} exact={route.exact} strict={route.strict} render={(props) => { if (!route.requiresAuth || authed || route.path === authPath) { return <route.component {...props} {...extraProps} route={route} /> } return <Redirect to={{ pathname: authPath, state: { from: props.location } }} /> }} /> ))} </Switch> ) : null export default renderRoutes
修改后的源码增加了两个参数 authed 、 authPath 和一个属性 route.requiresAuth
然后再来看一下最关键的一段代码
if (!route.requiresAuth || authed || route.path === authPath) { return <route.component {...props} {...extraProps} route={route} /> } return <Redirect to={{ pathname: authPath, state: { from: props.location } }} />
很简单 如果 route.requiresAuth = false 或者 authed = true 或者 route.path === authPath(参数默认值'/login')则渲染我们页面,否则就渲染我们设置的 authPath 页面,并记录从哪个页面跳转。
相应的router.js也要稍微修改一下
const routes = [ { path: 'https://www.jb51.net/', exact: true, component: Home, requiresAuth: false, }, { path: '/login', component: Login, requiresAuth: false, }, { path: '/user', component: User, requiresAuth: true, //需要登陆后才能跳转的页面 }, { path: '*', component: NotFound, requiresAuth: false, } ]
//app.js
import React from 'react' import { Switch } from 'react-router-dom' //import { renderRoutes } from 'react-router-config' import renderRoutes from './utils/renderRoutes' import routes from './router.js' const authed = false // 如果登陆之后可以利用redux修改该值(关于redux不在我们这篇文章的讨论范围之内) const authPath = '/login' // 默认未登录的时候返回的页面,可以自行设置 const App = () => ( <main> <Switch> {renderRoutes(routes, authed, authPath)} </Switch> </main> ) export default App
//登陆之后返回原先要去的页面login函数 login(){ const { from } = this.props.location.state || { from: { pathname: 'https://www.jb51.net/' } } // authed = true // 这部分逻辑自己写吧。。。 this.props.history.push(from.pathname) }
到此 react-router-config 就结束了并完成了我们想要的效果
3、注意:
很多人会发现,有时候达不到我们想要的效果,那么怎么办呢,接着往下看
1、设计全局组建来管理是否登陆
configLogin.js
import React, { Component } from 'react' import PropTypes from 'prop-types' import { withRouter } from 'react-router-dom' class App extends Component { static propTypes = { children: PropTypes.object, location: PropTypes.object, isLogin: PropTypes.bool, history: PropTypes.object }; componentDidMount () { if (!this.props.isLogin) { setTimeout(() => { this.props.history.push('/login') }, 300) } if (this.props.isLogin && this.props.location.pathname === '/login') { setTimeout(() => { this.props.history.push('https://www.jb51.net/') }, 300) } } componentDidUpdate () { if (!this.props.isLogin) { setTimeout(() => { this.props.history.push('/login') }, 300) } } render () { return this.props.children } } export default withRouter(App)
通过在主路由模块index.js中引入
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom' <Router history={ history } basename="https://www.jb51.net/" getUserConfirmation={ getConfirmation(history, 'yourCallBack') } forceRefresh={ !supportsHistory } > <App isLogin={ isLogin ? true : false }> <Switch> <Route exact path="https://www.jb51.net/" render={ () => <Redirect to="/layout/dashboard" push /> } /> <Route path="/login" component={ Login } /> <Route path="/layout" component={ RootLayout } /> <Route component={ NotFound } /> </Switch> </App> </Router>
很多时候我们是可以通过监听路由变化实现的比如 getUserConfirmation 钩子就是做这件事情的
const getConfirmation = (message, callback) => { if (!isLogin) { message.push('/login') } else { message.push(message.location.pathname) }
接下来我们看一下 react-acl-router 又是怎么实现的
四、权限管理机制本节参考代码: