react router4+redux实现路由权限控制

前端之家收集整理的这篇文章主要介绍了react router4+redux实现路由权限控制前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

总体概述

一个完善的路由系统应该是这样子的,当链接到的组件是需要登录后才能查看,要能够跳转登录页,然后登录成功后又跳回来之前想访问的页面。这里主要是用一个权限控制类来定义路由路由信息,同时用redux把登录成功后要访问的路由地址给保存起来,登录成功时看redux里面有没有存地址,如果没有存地址就跳转到默认路由地址。

路由权限控制类

在这个方法里面,通过sessionStorage判断是否登录了,如果没有登录,就保存一下当前想要跳转的路由到redux里面。然后跳转到我们登录页。

  1. import React from 'react'
  2. import { Route,Redirect } from 'react-router-dom'
  3. import { setLoginRedirectUrl } from '../actions/loginAction'
  4.  
  5. class AuthorizedRoute extends React.Component {
  6. render() {
  7. const { component: Component,...rest } = this.props
  8. const isLogged = sessionStorage.getItem("userName") != null ? true : false;
  9. if(!isLogged) {
  10. setLoginRedirectUrl(this.props.location.pathname);
  11. }
  12. return (
  13. <Route {...rest} render={props => {
  14. return isLogged
  15. ? <Component {...props} />
  16. : <Redirect to="/login" />
  17. }} />
  18. )
  19. }
  20. }
  21.  
  22. export default AuthorizedRoute

路由定义信息

路由信息也很简单。只是对需要登录后才能查看的路由用AuthorizedRoute定义。

  1. import React from 'react'
  2. import { BrowserRouter,Switch,Route,Redirect } from 'react-router-dom'
  3.  
  4. import Layout from '../pages/layout/Layout'
  5. import Login from '../pages/login/Login'
  6. import AuthorizedRoute from './AuthorizedRoute'
  7. import NoFound from '../pages/noFound/NoFound'
  8. import Home from '../pages/home/Home'
  9. import Order from '../pages/Order/Order'
  10. import WorkOrder from '../pages/Order/WorkOrder'
  11.  
  12. export const Router = () => (
  13. <BrowserRouter>
  14. <div>
  15. <Switch>
  16. <Route path="/login" component={Login} />
  17. <Redirect from="/" exact to="/login"/>{/*注意redirect转向的地址要先定义好路由*/}
  18. <AuthorizedRoute path="/layout" component={Layout} />
  19. <Route component={NoFound}/>
  20. </Switch>
  21. </div>
  22. </BrowserRouter>
  23. )

登录

就是把存在redux里面的地址给取出来,登录成功后就跳转过去,如果没有就跳转到默认页面,我这里是默认跳到主页。因为用了antd的表单,代码有点长,只需要看连接redux那两句和handleSubmit里面的内容

  1. import React from 'react'
  2. import './Login.css'
  3. import { login } from '../../mock/mock'
  4. import { Form,Icon,Input,Button,CheckBox } from 'antd';
  5. import { withRouter } from 'react-router-dom';
  6. import { connect } from 'react-redux'
  7. const FormItem = Form.Item;
  8.  
  9. class NormalLoginForm extends React.Component {
  10. constructor(props) {
  11. super(props);
  12. this.isLogging = false;
  13. }
  14. handleSubmit = (e) => {
  15. e.preventDefault();
  16. this.props.form.validateFields((err,values) => {
  17. if (!err) {
  18. this.isLogging = true;
  19. login(values).then(() => {
  20. this.isLogging = false;
  21. let toPath = this.props.toPath === '' ? '/layout/home' : this.props.toPath
  22. this.props.history.push(toPath);
  23. })
  24. }
  25. });
  26. }
  27. render() {
  28. const { getFieldDecorator } = this.props.form;
  29. return (
  30. <Form onSubmit={this.handleSubmit.bind(this)} className="login-form">
  31. <FormItem>
  32. {getFieldDecorator('userName',{
  33. rules: [{ required: true,message: 'Please input your username!' }],})(
  34. <Input prefix={<Icon type="user" style={{ color: 'rgba(0,.25)' }} />} placeholder="Username" />
  35. )}
  36. </FormItem>
  37. <FormItem>
  38. {getFieldDecorator('password',message: 'Please input your Password!' }],})(
  39. <Input prefix={<Icon type="lock" style={{ color: 'rgba(0,.25)' }} />} type="password" placeholder="Password" />
  40. )}
  41. </FormItem>
  42. <FormItem>
  43. {getFieldDecorator('remember',{
  44. valuePropName: 'checked',initialValue: true,})(
  45. <CheckBox>Remember me</CheckBox>
  46. )}
  47. <a className="login-form-forgot" href="">Forgot password</a>
  48. <Button type="primary" htmlType="submit" className="login-form-button"
  49. loading={this.isLogging ? true : false}>
  50. {this.isLogging ? 'Loging' : 'Login'}
  51. </Button>
  52. Or <a href="">register now!</a>
  53. </FormItem>
  54. </Form>
  55. );
  56. }
  57. }
  58.  
  59. const WrappedNormalLoginForm = Form.create()(NormalLoginForm);
  60.  
  61. const loginState = ({ loginState }) => ({
  62. toPath: loginState.toPath
  63. })
  64.  
  65. export default withRouter(connect(
  66. loginState
  67. )(WrappedNormalLoginForm))

顺便说一下这里redux的使用吧。我暂时只会基本使用方法:定义reducer,定义actions,创建store,然后在需要使用redux的变量时候去connect一下redux,需要dispatch改变变量时,就直接把actions里面的方法引入,直接调用就可以啦。为了让actions和reducer里面的事件名称对的上,怕打错字和便于后面修改吧,我建了个actionsEvent.js来存放事件名称
reducer:

  1. import * as ActionEvent from '../constants/actionsEvent'
  2.  
  3. const initialState = {
  4. toPath: ''
  5. }
  6.  
  7. const loginRedirectPath = (state = initialState,action) => {
  8. if(action.type === ActionEvent.Login_Redirect_Event) {
  9. return Object.assign({},state,{
  10. toPath: action.toPath
  11. })
  12. }
  13. return state;
  14. }
  15.  
  16. export default loginRedirectPath

actions:

  1. import store from '../store'
  2. import * as ActionEvent from '../constants/actionsEvent'
  3.  
  4. export const setLoginRedirectUrl = (toPath) => {
  5. return store.dispatch({
  6. type: ActionEvent.Login_Redirect_Event,toPath: toPath
  7. })
  8. }

创建store

  1. import { createStore,combineReducers } from 'redux'
  2. import loginReducer from './reducer/loginReducer'
  3.  
  4. const reducers = combineReducers({
  5. loginState: loginReducer //这里的属性名loginState对应于connect取出来的属性
  6. })
  7.  
  8. const store = createStore(reducers)
  9.  
  10. export default store

差点忘记说了,路由控制类AuthorizedRoute参考了https://codepen.io/bradwestfa... 这里的代码。感觉这份代码挺不错的,我一开始不会做就是看懂它才有点思路。

猜你在找的React相关文章