视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
react router4+redux实现路由权限控制的方法
2020-11-27 22:15:17 责编:小采
文档


总体概述

一个完善的路由系统应该是这样子的,当链接到的组件是需要登录后才能查看,要能够跳转到登录页,然后登录成功后又跳回来之前想访问的页面。这里主要是用一个权限控制类来定义路由路由信息,同时用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 这里的代码。感觉这份代码挺不错的,我一开始不会做就是看懂它才有点思路。

下载本文
显示全文
专题