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


Posted in Javascript onMay 03, 2018

总体概述

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

路由权限控制类

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

import React from 'react'
import { Route, Redirect } from 'react-router-dom'
import { setLoginRedirectUrl } from '../actions/loginAction'

class AuthorizedRoute extends React.Component {
  render() {
    const { component: Component, ...rest } = this.props
    const isLogged = sessionStorage.getItem("userName") != null ? true : false;
    if(!isLogged) {
      setLoginRedirectUrl(this.props.location.pathname);
    }
    return (
        <Route {...rest} render={props => {
          return isLogged
              ? <Component {...props} />
              : <Redirect to="/login" />
        }} />
    )
  }
}

export default AuthorizedRoute

路由定义信息

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

import React from 'react'
import { BrowserRouter, Switch, Route, Redirect } from 'react-router-dom'

import Layout from '../pages/layout/Layout'
import Login from '../pages/login/Login'
import AuthorizedRoute from './AuthorizedRoute'
import NoFound from '../pages/noFound/NoFound'
import Home from '../pages/home/Home'
import Order from '../pages/Order/Order'
import WorkOrder from '../pages/Order/WorkOrder'

export const Router = () => (
    <BrowserRouter>
      <div>
        <Switch>
          <Route path="/login" component={Login} />
          <Redirect from="/" exact to="/login"/>{/*注意redirect转向的地址要先定义好路由*/}
          <AuthorizedRoute path="/layout" component={Layout} />
          <Route component={NoFound}/>
        </Switch>
      </div>
    </BrowserRouter>
)

登录页

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

import React from 'react'
import './Login.css'
import { login } from '../../mock/mock'
import { Form, Icon, Input, Button, Checkbox } from 'antd';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux'
const FormItem = Form.Item;

class NormalLoginForm extends React.Component {
  constructor(props) {
    super(props);
    this.isLogging = false;
  }
  handleSubmit = (e) => {
    e.preventDefault();
    this.props.form.validateFields((err, values) => {
      if (!err) {
        this.isLogging = true;
        login(values).then(() => {
          this.isLogging = false;
          let toPath = this.props.toPath === '' ? '/layout/home' : this.props.toPath
          this.props.history.push(toPath);
        })
      }
    });
  }
  render() {
    const { getFieldDecorator } = this.props.form;
    return (
        <Form onSubmit={this.handleSubmit.bind(this)} className="login-form">
          <FormItem>
            {getFieldDecorator('userName', {
              rules: [{ required: true, message: 'Please input your username!' }],
            })(
                <Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
            )}
          </FormItem>
          <FormItem>
            {getFieldDecorator('password', {
              rules: [{ required: true, message: 'Please input your Password!' }],
            })(
                <Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
            )}
          </FormItem>
          <FormItem>
            {getFieldDecorator('remember', {
              valuePropName: 'checked',
              initialValue: true,
            })(
                <Checkbox>Remember me</Checkbox>
            )}
            <a className="login-form-forgot" href="">Forgot password</a>
            <Button type="primary" htmlType="submit" className="login-form-button"
                loading={this.isLogging ? true : false}>
              {this.isLogging ? 'Loging' : 'Login'}
            </Button>
            Or <a href="">register now!</a>
          </FormItem>
        </Form>
    );
  }
}

const WrappedNormalLoginForm = Form.create()(NormalLoginForm);

const loginState = ({ loginState }) => ({
  toPath: loginState.toPath
})

export default withRouter(connect(
    loginState
)(WrappedNormalLoginForm))

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

import * as ActionEvent from '../constants/actionsEvent'

const initialState = {
  toPath: ''
}

const loginRedirectPath = (state = initialState, action) => {
  if(action.type === ActionEvent.Login_Redirect_Event) {
    return Object.assign({}, state, {
      toPath: action.toPath
    })
  }
  return state;
}

export default loginRedirectPath

actions:

import store from '../store'
import * as ActionEvent from '../constants/actionsEvent'

export const setLoginRedirectUrl = (toPath) => {
  return store.dispatch({
         type: ActionEvent.Login_Redirect_Event,
        toPath: toPath
       })
}

创建store

import { createStore, combineReducers } from 'redux'
import loginReducer from './reducer/loginReducer'

const reducers = combineReducers({
  loginState: loginReducer //这里的属性名loginState对应于connect取出来的属性名
})

const store = createStore(reducers)

export default store

差点忘记说了,路由控制类AuthorizedRoute参考了https://codepen.io/bradwestfall/project/editor/XWNWge?preview_height=50&open_file=src/app.js 这里的代码。感觉这份代码挺不错的,我一开始不会做就是看懂它才有点思路。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
当jQuery遭遇CoffeeScript的时候 使用分享
Sep 17 Javascript
onkeypress字符按键兼容所有浏览器使用介绍
Apr 24 Javascript
jQuery控制TR显示隐藏的几种方法
Jun 18 Javascript
javascript比较两个日期的先后示例代码
Dec 31 Javascript
JavaScript 弹出子窗体并返回结果到父窗体的实现代码
May 28 Javascript
js中利用cookie实现记住密码功能
Aug 20 Javascript
Bootstrap fileinput组件封装及使用详解
Mar 10 Javascript
AngularJS 单选框及多选框的双向动态绑定
Apr 20 Javascript
AngularJS获取json数据的方法详解
May 27 Javascript
前端把html表格生成为excel表格的实例
Sep 19 Javascript
Vue项目移动端滚动穿透问题的实现
May 19 Javascript
用vue写一个日历
Nov 02 Javascript
vue.js学习笔记之v-bind和v-on解析
May 03 #Javascript
jQuery实现每隔一段时间自动更换样式的方法分析
May 03 #jQuery
详解VueJs中的V-bind指令
May 03 #Javascript
基于vue,vue-router, vuex及addRoutes进行权限控制问题
May 02 #Javascript
用ES6写全屏滚动插件的示例代码
May 02 #Javascript
详解Vue中watch的高级用法
May 02 #Javascript
Vue.js中关于侦听器(watch)的高级用法示例
May 02 #Javascript
You might like
PHP中子类重载父类的方法【parent::方法名】
2016/05/06 PHP
PHP实现一个多功能购物网站的案例
2017/09/13 PHP
PHP延迟静态绑定的深入讲解
2018/04/02 PHP
网页常用特效代码整理
2006/06/23 Javascript
jquery封装的对话框简单实现
2013/07/21 Javascript
原生JavaScript实现连连看游戏(附源码)
2013/11/05 Javascript
jquery序列化form表单使用ajax提交后处理返回的json数据
2014/03/03 Javascript
jquery仿百度经验滑动切换浏览效果
2015/04/14 Javascript
移动端滑动插件Swipe教程
2016/10/16 Javascript
在一个页面重复使用一个js函数的方法详解
2016/12/26 Javascript
Vue.js实现一个todo-list的上移下移删除功能
2017/06/26 Javascript
原生JS实现移动端web轮播图详解(结合Tween算法造轮子)
2017/09/10 Javascript
vue-router 组件复用问题详解
2018/01/22 Javascript
jQuery实现的五星点评功能【案例】
2019/02/18 jQuery
小程序开发踩坑:页面窗口定位(相对于浏览器定位)(推荐)
2019/04/25 Javascript
vue实现拖拽效果
2019/12/23 Javascript
Vant 在vue-cli 4.x中按需加载操作
2020/11/05 Javascript
[01:39:04]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第二场 2月1日
2021/03/11 DOTA
在Python中使用列表生成式的教程
2015/04/27 Python
Python实现曲线拟合操作示例【基于numpy,scipy,matplotlib库】
2018/07/12 Python
python笔记之mean()函数实现求取均值的功能代码
2019/07/05 Python
俄罗斯Sportmarket体育在线商店:用于旅游和户外活动
2019/11/12 全球购物
万豪国际住宅与别墅集团:Homes & Villas by Marriott International
2020/10/08 全球购物
三年大学自我鉴定
2014/01/16 职场文书
服务生自我鉴定
2014/01/22 职场文书
2014年商场超市庆元旦活动方案
2014/02/14 职场文书
优质服务演讲稿
2014/05/14 职场文书
节水口号标语
2014/06/19 职场文书
餐饮服务食品安全责任书
2014/07/25 职场文书
八荣八耻的活动方案
2014/08/16 职场文书
2015年全国爱耳日活动总结
2015/02/27 职场文书
何玥事迹观后感
2015/06/16 职场文书
房屋质量投诉书
2015/07/02 职场文书
python中如何对多变量连续赋值
2021/06/03 Python
使用redis实现延迟通知功能(Redis过期键通知)
2021/09/04 Redis
Java工作中实用的代码优化技巧分享
2022/04/21 Java/Android