react实现路由守卫

在开发中可能经常会遇到有关权限的问题,比如用户如果没有登陆的话是查看不了个人信息的.今天基于前面react-redux和react路由两篇文章的代码做一些修改来实现路由守卫的功能.
首先来修改一下src/store/login-redux.js

src/store/login-redux.js

const initState = {
    login: false,
    loading: false
}
export const loginReducer = (state=initState, action) => {
    switch(action.type){
        case "nowlogin":
            return {
                login: false,
                loading: true
            }
        case "haslogin":
            return {
                login: true,
                loading: false
            }
        default :
            return state
    }
}

export const asyncLogin  = () => dispatch =>{
    dispatch({type: "nowlogin"});
    setTimeout(() => {dispatch({type: "haslogin"})}, 1500)
}

然后去修改src/routerdemo.js文件,在这只展示修改过的地方,其余代码和react路由文章中代码一样

src/routerdemo.js

//页面引入登陆事件以及connent
import { connect } from "react-redux"
import { asyncLogin } from "./store/login-redux"
//首先我们来写权限控制组件,我们按照思路逐渐完善组件
//第一版我们需要写一个高阶组件让他返回一个Route组件,Route组件上面的属性我们需要根据redux中传过来的登陆状态动态判断应该展示的组件
function Permission ({component: Com,isLogin, ...rest})  {//因为组件名要大写所以需要给component取别名,isLogin登陆状态,rest组件其他属性
        return (
//Redirect中的to属性可以是字符串也可以是对象,我们在state属性中存储登陆后直接跳转的地址可在location中获取到
            <Route {...rest} render={({location, ...other}) => isLogin? <Com {...other}></Com> : <Redirect to={{pathname: "/login", state:{jumpUrl: location.pathname}}} ></Redirect>}></Route>
        )
    }
//第一版已经理清我们的思路了,那么缺少的就是登陆的状态了,我们接下来把组件完成
//因为Permission组件只需要登陆状态所以我们只需要给connect传入第一个参数就即可,connect也会返回一个组件我们只需要把他赋值给Permission
const Permission = connect(state => ({isLogin: state.login.login}))(
    ({component: Com,isLogin, ...rest}) => {
        return (
            <Route {...rest} render={({location, ...other}) => isLogin? <Com {...other}></Com> : <Redirect to={{pathname: "/login", state:{jumpUrl: location.pathname}}} ></Redirect>}></Route>
        )
    }
)

上面完成了对权限路由的处理,现在我们来处理登陆组件

//第一版同样先理思路
function Login ({location, isLogin, loading, asyncLogin}){//location重定向到路由组件后要获取的地址
          //isLogin,loading都是登陆状态
          //asyncLogin异步登陆事件
        const fromUrl = location.state&&location.state.jumpUrl || "/"; //如果location.state中有jumpUrl就采用没有就跳转到首页
        if(isLogin){//如果登陆了就重定向到制定的页面,否则展示下面的登陆表单登陆
            return <Redirect to={fromUrl}></Redirect>
        }
        return(
            <div>
                <button onClick={asyncLogin}>{loading? "登录中..." : "登陆"}</button>
            </div>
        )
    }
//登陆组件的参数中我们还需要拿到isLogin, loading, asyncLogin,下来我们完善他
const Login = connect(state => ({
  isLogin: state.login.login, //登陆状态
  loading: state.login.loading}),//是否正在请求登陆
  {asyncLogin})(
    function ({location, isLogin, loading, asyncLogin}){
        const fromUrl = location.state&&location.state.jumpUrl || "/";
        if(isLogin){
            return <Redirect to={fromUrl}></Redirect>
        }
        return(
            <div>
                <button onClick={asyncLogin}>{loading? "登录中..." : "登陆"}</button>
            </div>
        )
    }
)

接下来就可以去使用我们的权限组件Permission了,我们需要对哪个组件做权限直接用Permission替换他,我们替换之前写的那个

export default function Routerdemo(){
    return (
        <Router>
            <div style={{marginBottom:"15px"}}>
                <Link to="/">首页 </Link>&nbsp;&nbsp;&nbsp;&nbsp;
                <Link to="/about">关于</Link>&nbsp;&nbsp;&nbsp;&nbsp;
                <Link to="/person">用户中心</Link>&nbsp;&nbsp;&nbsp;&nbsp;
                <Link to="/search">发现</Link>
            </div>
            <Switch>
                <Route exact path="/" component={Home}></Route>
                <Route path="/about" component={About}></Route>
                <Permission path="/person" component={Person}></Permission>//将Person组件传进去
                {/* <Route path="/person" component={Person}></Route> */}
                <Route path="/login" component={Login}></Route>
                <Route component={Nopage}></Route>
            </Switch>
        </Router>
    )
}

查看页面效果


1.gif
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341