React路由,路由权限认证,子路由权限认证

此文为个人学习记录文章,若有不足,请勿吐槽。多多指教

目的:只需按需求配置路由树route,然后在需要渲染的地方引入路由组件,即可实现包括子路由在内的层级渲染,子路由的第一个路由配置默认为首次渲染所需的路由,并且包含各层路由的权限认证。权限认证通过后访问对应页面,反之,跳转登录页面。若已登录,但手动使路由跳转到登录页,则会重定向到首页。

实现效果图一(初始效果):红框位置为对应路由所渲染的位置。

 示例:

        一级路由位置:对应路由为:‘/’,对应页面为:“index.jsx”

        二级路由位置:对应路由为:‘/index1’,对应页面为:“index1.jsx”

        二级路由位置:对应路由为:‘/index1/index7’,对应页面为:“index7.jsx”

其中 /index1 为 /的子路由,且在路由树中的位置处于第一个, /index1/index7同理。

实现效果图二(未登录状态):点击按钮“第三个页面”,重定向到  登录页

实现效果图三(登录状态): 点击按钮“第三个页面”,页面渲染

 

代码:

app.js

import './App.css';
import React,{Suspense} from 'react'
import { Provider } from 'react-redux';
import LoginIndex from './component/loginAndRegist/index'
import {routerMap} from './route/index'
import store from './reducers/store'
import { BrowserRouter as Router, HashRouter, Route, Link, Switch, Redirect, withRouter, Prompt } from 'react-router-dom'
import FrontendAuth from './route/requireCredentials2';
function App() {
    // return <Routes />
    return (
        <div className="App">
            <Provider store={store}>
                {/* <React.StrictMode> */}
                    {/* <Router forceRefresh={false}>
                        {routes}
                    </Router> */}
                {/* </React.StrictMode> */}
                <Suspense fallback={<div>loading...</div>}>
                    <Router>
                        <Switch>
                            <FrontendAuth index="1"></FrontendAuth>
                        </Switch>
                    </Router>
                </Suspense>
            </Provider>
        </div>
    );
}

export default App;

route.js

路由树:其中level表示该路由处于第几级路由。auth:表示是否需要权限认证

import React,{lazy}from 'react'
import Login from './../component/loginAndRegist/login'
import Regist from './../component/loginAndRegist/regist'
import Index from './../component/loginAndRegist/index'
// import Index1 from './../component/loginAndRegist/index1'
// import Index2 from './../component/loginAndRegist/index2'
// import Index3 from './../component/loginAndRegist/index3'
import Err from './../component/test/err'
export const routeList=[
    {
        path:'/',
        component:lazy(() => import('@/component/loginAndRegist/index')),
        level:1,//对应路由组件上的index。表示当前路由在整个路由树中的层级
        child:[
            {
                path:'/index1',
                component:lazy(() => import('@/component/loginAndRegist/index1')),
                level:2,
                child:[
                   {
                        path:'/index1/index7',
                        level:3,
                        component:lazy(() => import('@/component/loginAndRegist/index7')),
                    }
                ]
            }, {
                path:'/index2',
                level:2,
                component:lazy(() => import('@/component/loginAndRegist/index2')),
            }, {
                path:'/index3',
                level:2,
                component:lazy(() => import('@/component/loginAndRegist/index3')),
                child:[
                    {
                        path:'/index3/index4',
                        level:3,
                        component:lazy(() => import('@/component/loginAndRegist/index4')),
                        auth:true
                    }, {
                        path:'/index3/index5',
                        level:3,
                        component:lazy(() => import('@/component/loginAndRegist/index5')),
                    }, {
                        path:'/index3/index6',
                        level:3,
                        component:lazy(() => import('@/component/loginAndRegist/index6')),
                        auth:true
                    },
                ]
            },
        ]
    },{
        path:'/login',
        component:Login,
        level:1
    },{
        path:'/regist',
        component:Regist,
        level:1
    },{
        path:'/err',
        component:lazy(() => import('@/component/test/err')),
        level:1
    }
]

requireCredentials2.js

路由验证组件,验证逻辑在这里面实现

/**

 * 监听路由变化,结合redux中是否登录,进行权限控制路由转变
 */

import React , {Fragment}from 'react'
import { connect } from 'react-redux'
import { Route, withRouter, Redirect } from 'react-router-dom'
import { routeList } from './route'

class FrontendAuth extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        const { routerConfig, location, match } = this.props;
        const { pathname } = location;
        const isLogin = (this.props.userMes.flag && this.props.userMes.flag != "") ? true : false;//判断是否登录的标志
        var data = [];
        var resultFlag = false;
        var index = this.props.index;
        // 将路由的第一个路由作为默认路由
        function getFirstChildToData(arr,array=[]){
            if(Array.isArray(arr)&&arr.length>0){
                var lin = {};
                if (arr[0]['path']) lin['path'] = arr[0]['path'];
                if (arr[0]['component']) lin['component'] = arr[0]['component'];
                if (arr[0]['exact']) lin['exact'] = arr[0]['exact'];
                if (arr[0]['strict']) lin['strict'] = arr[0]['strict'];
                if (arr[0]['child']) lin['child'] = arr[0]['child'];
                if (arr[0]['auth']) lin['auth'] = arr[0]['auth'];
                if (arr[0]['level']) lin['level'] = arr[0]['level'];
                lin['index'] = true;
                array.push(lin);
                if(arr[0]['child'])getFirstChildToData(arr[0]['child'],array);
            }
        }
        function findRoute(arr) {
            var result = [];
            for (var i = 0; i < arr.length; i++) {
                if (arr[i]['path'] == pathname) {
                    resultFlag = true;
                    var lin = {};
                    if (arr[i]['path']) lin['path'] = arr[i]['path'];
                    if (arr[i]['component']) lin['component'] = arr[i]['component'];
                    if (arr[i]['exact']) lin['exact'] = arr[i]['exact'];
                    if (arr[i]['strict']) lin['strict'] = arr[i]['strict'];
                    if (arr[i]['child']) lin['child'] = arr[i]['child'];
                    if (arr[i]['auth']) lin['auth'] = arr[i]['auth'];
                    if (arr[i]['index']) lin['index'] = arr[i]['index'];
                    if (arr[i]['level']) lin['level'] = arr[i]['level'];
                    result.push(lin);
                    if(arr[i]['child'])getFirstChildToData(arr[i]['child'],result)
                    return result;
                } else if (arr[i]['child']) {
                    var res = findRoute(arr[i]['child']);
                    if(res){
                        var lin = {};
                        if (arr[i]['path']) lin['path'] = arr[i]['path'];
                        if (arr[i]['component']) lin['component'] = arr[i]['component'];
                        if (arr[i]['exact']) lin['exact'] = arr[i]['exact'];
                        if (arr[i]['strict']) lin['strict'] = arr[i]['strict'];
                        if (arr[i]['child']) lin['child'] = arr[i]['child'];
                        if (arr[i]['auth']) lin['auth'] = arr[i]['auth'];
                        if (arr[i]['index']) lin['index'] = arr[i]['index'];
                        if (arr[i]['level']) lin['level'] = arr[i]['level'];
                        return result.concat(lin).concat(res);
                    }
                }
            }
        }
        // 从路由树中找到匹配的路由,将需要被渲染的路由转换成数组,数组的顺序即为需要渲染的顺序
        data = findRoute(routeList);
        /***
         * 若当前路由未在路由树中找到,则跳转到指定页面
         */
  
        if (!resultFlag) {
            return <Redirect to="/err" />;
        }
        var target = data[parseInt(index) - 1];
        if(!(target&&(target.level+''===index+''))){
            return <Redirect to="/err" />;
        }
        if (isLogin) {
            // 如果是登陆状态,想要跳转到登陆,重定向到主页
            if (pathname === "/login") {
                return <Redirect to="/" />;
            } else {
                // 如果路由合法,就跳转到相应的路由
                if (target) {
                    return target.index?<Route component={target.component} index />:<Route path={target.path} component={target.component}/>
                } else {
                    // 如果路由不合法,重定向到 404 页面
                    return <Redirect to="/err" />;
                }
            }
        } else {
            // 非登陆状态下,当路由合法时且需要权限校验时,跳转到登陆页面,要求登陆
            if(target&&target.auth&&target.auth==true){
                return <Redirect to="/login" />;
            }else if(target&&((target.auth&&target.auth==false)||!target.auth)){
                if(target)return target.index?<Route component={target.component} index />:<Route path={target.path} component={target.component}/>
                else return <Fragment></Fragment>;
            }else{
                console.log(target)
                return <Redirect to="/err" />;
            }
        }
    }
}
// 将 store 中的数据作为 props 绑定到组件上 
const mapStateToProps = (state) => {
    return {
        userMes: state.auth
    }
}
// 将 action 作为 props 绑定到组件上。
const mapDispatchToProps = (dispatch) => {
    return {
        // userAction:bindActionCreators(userAction,dispatch)
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(FrontendAuth))

index.jsx

       “第一个按钮” 对应的页面。FrontendAuth组件 对应requireCredentials2.js,其中它的参数index必须与路由树的“level”对应。子路由想在哪渲染,就在哪添加上这个组件就行

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from "redux"
import { Route, Link , Redirect } from 'react-router-dom'
import * as userAction from '../../action/userAction'
import Index1 from './index1'
import Index2 from './index2'
import index3 from './index3'
import FrontendAuth from '../../route/requireCredentials2'
import './login.css'
class Index extends Component {
    constructor(props) {
        super(props);
        // console.log(this.props.match.path)
    }
    render() {
        const routerMap = [
            <Route index path="/index/index1" component={Index1}></Route>,
            <Route exact strict path="/index/index2" component={Index2}></Route>,
            <Route exact strict path="/index/index3" auth="true" component={index3}></Route>,
            <Redirect to="/err"></Redirect>
        ]
        return (
            <div className="bigBox">
                <div className="switchBox">
                    <div className="box">
                        <Link to="/index1" className="loginBtn">第一个页面</Link>
                        <Link to="/index2" className="loginBtn">第二个页面</Link>
                        <Link to="/index3" className="loginBtn">第三个页面(权限验证)</Link>
                        <Link to="/login" className="loginBtn">跳转到登录页</Link>
                        <Link to="/regist" className="loginBtn">跳转到注册页</Link>
                        <Link to="/err" className="loginBtn">跳转到404</Link>
                    </div>
                    <div className="loginState">登录状态:{this.props.userMes.flag}</div>
                    <div className="loginState">商品信息:{this.props.shopMes.name}</div>
                    {/* <Switch>
                        <Route exact strict path="/index" component={Index2}></Route>,
                        <Route exact strict path="/index/index3" auth="true" component={index3}></Route>
                        <Redirect to="/err"></Redirect>
                    </Switch> */}
                    <FrontendAuth index="2"></FrontendAuth>
                </div>
            </div>
        )
    }
}
// 将 store 中的数据作为 props 绑定到组件上 
const mapStateToProps = (state) => {
    return {
        userMes: state.auth,
        shopMes: state.shop
    }
}
// 将 action 作为 props 绑定到组件上。
const mapDispatchToProps = (dispatch) => {
    return {
        userAction: bindActionCreators(userAction, dispatch)
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(Index)

index1.jsx

“第一个按钮” 对应的页面,属于index.jsx的子页面;FrontendAuth组件 对应requireCredentials2.js,其中它的参数index必须与路由树的“level”对应。子路由想在哪渲染,就在哪添加上这个组件就行

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from "redux"
import * as userAction from '../../action/userAction'
import FrontendAuth from '@/route/requireCredentials2'
import './login.css'
class index1 extends Component {
    constructor(props) {
        super(props);
        console.log(this.props.match.path)
    }
    render() {
        return (
            <div className="bigBox">
               我是主页的第一个页面
               <FrontendAuth index="3"></FrontendAuth>
            </div>
        )
    }
}
// 将 store 中的数据作为 props 绑定到组件上 
const mapStateToProps = (state) => {
    return {
        userMes: state.auth,
        shopMes: state.shop
    }
}
// 将 action 作为 props 绑定到组件上。
const mapDispatchToProps = (dispatch) => {
    return {
        userAction: bindActionCreators(userAction, dispatch)
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(index1)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值