reat hooks实现全局拦截守卫

----------------------------续----------------------------------------

前面写了一篇文章,关于全局拦截守卫。虽然实现了全局拦截。但是并不完美。我们只能针对一级路由有效。也就是整个routes数组只有一层。如果还有嵌套路由,二级,三级,就无能为力。因为我们在页面切换的时候,我们想获取到当前路由path和数组中匹配的那条数据,是通过    const targetRouteObj = routeData.find((item) => item.path == pathname)这个方法实现的。而这个方法只做到了一层。

想一想还有没有更好的办法实现路由守卫呢?今天尝试用另外一种方法来实现,并且它支持嵌套路由:

-------------------------------------app.js-----------------------------------------------

import React from 'react'

 

import { BrowserRouter as Router, Switch, Route } from "react-router-dom"

import routes from "./router/routes"

import AuthRoute from "./router/authRoute"

import { MainRoute } from "./router/routeConfig"

function App() {

  return (

    <MainRoute></MainRoute>

  );

}

export default App;

--------------------------------routes.js-----------------------------------------------------

import React from 'react'

 

import Layout from "../pages/Layout"

import Login from "../pages/Login"

import About from "../pages/About"

import NotFound from "../pages/NotFound"

import UserInfo from "../pages/UserInfo"

import Info from "../pages/Info"

import News from "../pages/News"

import Product from "../pages/Product"

const routes = [

    { name: "", path: "/", component:Login, children:[],exact:true},

    { name: "login", path: "/login", component:Login,children:[],exact:false},

    {

        name: "layout",

        path: "/layout",

        auth: true,

        component: Layout,

        exact:false,

        children: [

            {

                path: "/layout/news",

                name: "news",

                auth: true,

                component: News

            },

            {

                path: "/layout/product",

                name: "product",

                auth: true,

              

                component: Product

            },

            {

                path: "/layout/userInfo",

                name: "userInfo",

                auth:true,

                component: UserInfo

            },

             {

                path: "/",

                name: "news",

                auth: true,

               

                component: News

            },

        ],

    },

    { name: "about", path: "/about", component: About,children:[],auth:true, exact: false },   

    { name: "info", path: "/info", component: Info,children:[],auth:false, exact: false },   

    { name: "404", path: "/404", component: NotFound,children:[], exact: false },   

]

export default routes;

 

 

--------------------------------routeConfig.js-----------------------------------------------------

import React from 'react'

import routes from "./routes"

import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom"

import Layout from "../pages/Layout"

//一级路由

const MainRoute = () => { 

    return (

        <Router>

            <Switch>

                {

                    routes.map((item, index) => { 

                        if (item.auth) {

                            console.log("1111")

                            return (

                                <PrivateRoute

                                    key={index}

                                    path={item.path}

                                    {...item}

                                    component={item.component }

                                >

                                </PrivateRoute>

                            )

                        } else { 

                            return (<NormalRoute key={index} {...item}></NormalRoute>)

                        }

                    })   

                }

                <Redirect to="/404"></Redirect>

            </Switch>

        </Router>        

    )

}

//二级路由

function SubRoute() {

    const subRoutes = routes&&routes.filter(item => item.children.length > 0)[0]['children']

    return (

        <Switch>

            {subRoutes.map((item,index) => { 

                if (item.auth) {

                    return (

                        <PrivateRoute

                            key={index}

                            path={item.path}

                            {...item}

                            component={ item.component}

                        >

                        </PrivateRoute>

                    )

                } else { 

                    return (<NormalRoute key={index} {...item}></NormalRoute>)

                }

            })}

            <Redirect to="/404"></Redirect>

        </Switch>   

    )

}

//私有路由,需要拦截

const PrivateRoute = (props) => { 

    let isLogin = localStorage.getItem("isLogin")

    let { location } = props;

    return (

        <Route render={

            () => { 

                if (isLogin) {

                    return (<Route path={props.path} component={props.component }></Route>)

                } else { 

                    return <Redirect to="/" ></Redirect>

                }                   

            }

        }>

        </Route>

    )

}

//开放路由,无须拦截

const NormalRoute = (route) => {     

    let { location } = route;

        return (

            <Route

                exact={route.exact}

                path={route.path}

                component={ route.component}

            >

            </Route>

        )

}

export { MainRoute,SubRoute}

-------------------------------------------layout.js----------------------------------------------

import React from 'react'

import { useHistory} from "react-router-dom"

import homeStyle from "./home.module.less"

import MainNav from "../MainNemu"

import { SubRoute } from "../../router/routeConfig"

function Layout() { 

    let history=useHistory()

    const loginOut = () => { 

        localStorage.clear()

        history.replace("/login")

    }

    return (

        <div className={homeStyle['layout-container']}>

            <header className={homeStyle['layout-top']}>

                <img src="https://ali-image-test.dabanjia.com/image/20190320/DBJ_1553077801738_3899.png?x-oss-process=image/resize,m_lfit,h_80,w_300" alt=""/>

            </header>

            <main className={homeStyle['layout-main']}>

                <section className={homeStyle['layout-side']}>

                    <MainNav></MainNav>

                </section>

                <section className={homeStyle['layout-content']}>

                    <SubRoute></SubRoute>

                </section>

            </main>

        </div>        

    )

}

export default Layout

---------------------------------------login.js---------------------------------------------------

import React, { useState } from 'react'

import { useHistory } from "react-router-dom"

import { Button } from 'antd';

import "./login.css"

 

function Login() {  

    const [user,setUser]=useState("")

    const [password, setPassword] = useState("")

 

    let history=useHistory()

    console.log("登录history:", history)

    const getVal = (obj) => { 

        let type = obj.target.dataset.type

       

        if (type == "user") {

            setUser(obj.target.value)

        } else { 

            setPassword(obj.target.value)

        }        

    }

    const login = () => { 

        localStorage.setItem("isLogin", true)   

        history.push("/layout")

    }

    return (

        <div className="form-box">

            <p>

                <input type="text" name="" value={user } data-type="user" onChange={getVal} placeholder="请输入用户名"/>

            </p>

            <p>

                <input type="password" name="" value={ password} data-type="password" onChange={getVal} placeholder="请输入密码"/>

            </p>

            <p>用户名是:{ user }</p>

            <p>密码是:{ password}</p>

            <p>

                <Button type="primary" onClick={ login }>Primary Button</Button>

            </p>

        </div>

    )

}

export default Login

这个实例能实现全局守卫的作用。但是有一个缺陷点:就是在登录以后。如果手动输入url地址栏到login,还是会回到login页面。因为整体的逻辑是按照是否开放页面来区分的。login属于开放页面,所以即使登录了,还是可以回到登录、

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值