在開發(fā)中可能經(jīng)常會遇到有關(guān)權(quán)限的問題,比如用戶如果沒有登陸的話是查看不了個(gè)人信息的.今天基于前面react-redux和react路由兩篇文章的代碼做一些修改來實(shí)現(xiàn)路由守衛(wèi)的功能.
首先來修改一下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"
//首先我們來寫權(quán)限控制組件,我們按照思路逐漸完善組件
//第一版我們需要寫一個(gè)高階組件讓他返回一個(gè)Route組件,Route組件上面的屬性我們需要根據(jù)redux中傳過來的登陸狀態(tài)動態(tài)判斷應(yīng)該展示的組件
function Permission ({component: Com,isLogin, ...rest}) {//因?yàn)榻M件名要大寫所以需要給component取別名,isLogin登陸狀態(tài),rest組件其他屬性
return (
//Redirect中的to屬性可以是字符串也可以是對象,我們在state屬性中存儲登陸后直接跳轉(zhuǎn)的地址可在location中獲取到
<Route {...rest} render={({location, ...other}) => isLogin? <Com {...other}></Com> : <Redirect to={{pathname: "/login", state:{jumpUrl: location.pathname}}} ></Redirect>}></Route>
)
}
//第一版已經(jīng)理清我們的思路了,那么缺少的就是登陸的狀態(tài)了,我們接下來把組件完成
//因?yàn)镻ermission組件只需要登陸狀態(tài)所以我們只需要給connect傳入第一個(gè)參數(shù)就即可,connect也會返回一個(gè)組件我們只需要把他賦值給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>
)
}
)
上面完成了對權(quán)限路由的處理,現(xiàn)在我們來處理登陸組件
//第一版同樣先理思路
function Login ({location, isLogin, loading, asyncLogin}){//location重定向到路由組件后要獲取的地址
//isLogin,loading都是登陸狀態(tài)
//asyncLogin異步登陸事件
const fromUrl = location.state&&location.state.jumpUrl || "/"; //如果location.state中有jumpUrl就采用沒有就跳轉(zhuǎn)到首頁
if(isLogin){//如果登陸了就重定向到制定的頁面,否則展示下面的登陸表單登陸
return <Redirect to={fromUrl}></Redirect>
}
return(
<div>
<button onClick={asyncLogin}>{loading? "登錄中..." : "登陸"}</button>
</div>
)
}
//登陸組件的參數(shù)中我們還需要拿到isLogin, loading, asyncLogin,下來我們完善他
const Login = connect(state => ({
isLogin: state.login.login, //登陸狀態(tài)
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>
)
}
)
接下來就可以去使用我們的權(quán)限組件Permission了,我們需要對哪個(gè)組件做權(quán)限直接用Permission替換他,我們替換之前寫的那個(gè)
export default function Routerdemo(){
return (
<Router>
<div style={{marginBottom:"15px"}}>
<Link to="/">首頁 </Link>
<Link to="/about">關(guān)于</Link>
<Link to="/person">用戶中心</Link>
<Link to="/search">發(fā)現(xiàn)</Link>
</div>
<Switch>
<Route exact path="/" component={Home}></Route>
<Route path="/about" component={About}></Route>
<Permission path="/person" component={Person}></Permission>//將Person組件傳進(jìn)去
{/* <Route path="/person" component={Person}></Route> */}
<Route path="/login" component={Login}></Route>
<Route component={Nopage}></Route>
</Switch>
</Router>
)
}
查看頁面效果