1.React中路由守卫的实现
React
中没有类似于vue
中现成的路由守卫,React
中的路由守卫是通过高阶组件对Route
的封装。
下面梳理下思路,首先来看下App.js
(代码延用全家桶03中的一部分)的代码:
-
如果想要在匹配路由的时候判断是否
登录
,去显示不同组件,那么就需要使用高阶组件
对路由的Route
进行封装,过程中对是否登录状态
做处理,从而显示不同的内容。 -
PrivateRoute
是一个高阶组件,对传入他的参数进行解构(这里参数为SendComponent对应的Comp,还有path,但未对path解构
) -
通过
{...rest}
将原来参数中未解构的属性一起保留放Route
上,Route
的render接收一个函数,接收props
,引入Auth
并对其中的验证状态isAuth
做判断-
验证通过:返回---
<Comp {...props}/>
-
验证不通过:重定向---
<Redirect to={{pathname:'/login',state:{from:props.location}}} />
,这里通过state:{from:props.location}
把当前的路径
传递给了Login
组件中
-
//App.js
import React, {Component} from 'react';
import {BrowserRouter as Router,Route,Link,Switch,Redirect} from "react-router-dom";
import Home from "./pages/Home.js";
import NotFound from "./pages/NotFound";
import About from "./pages/About";
import Login from "./pages/Login";
import Auth from "./utils/auth";
// 🚀 高阶组件:定义验证功能的路由组件
function PrivateRoute({sendComponent:Comp,...rest}){
console.log("我是参数",arguments);
console.log("我是解构后的Comp",Comp);
return(
<Route
{...rest}
render={
(props)=>Auth.isAuth ? (<Comp {...props}/>):(<Redirect to={{pathname:'/login',state:{from:props.location}}} />)
}
>
</Route>
)
}
class App extends Component {
render() {
return (
<Router>
<ul>
<li>
<Link to="/"> 首页 </Link>
</li>
<li>
<Link to="/about"> 关于我 </Link>
</li>
</ul>
{/*路由配置*/}
<Switch>
{/*🚀①号*/}
<Route exact path="/home" component={Home} />
{/* 🚀PrivateRoute是个高阶组件 */}
<PrivateRoute path="/about" sendComponent={About}/>
<Route path="/login" component={Login}/>
{/* 🚀 这里要放在NotFound前面,因为Switch找到了符合条件的组件,就不往下面继续走了*/}
<Redirect to="/home"/>
<Route component={NotFound}/>
</Switch>
</Router>
);
}
}
export default App;
Auth.js
//javascript
const Auth = {
isAuth:false,
login(callback){
setTimeout(callback,1000);
this.isAuth = true;
}
}
export default Auth;
然后来看下Login.js
- 解构下之前传递过来的
state:{from:props.location}
参数到path
中,登录后就Redirect
回去了 - 如果没有
登录(isLogin为false)
或者Auth
中的验证状态是false
,那么就得走登录流程,修改后继续执行上一步操作。
import React, {Component} from 'react';
// 🚀 改变isLogin登录状态的同时也需要修改Auth的验证状态
import Auth from "../utils/auth";
import {Redirect} from "react-router-dom";
class Login extends Component {
constructor(props) {
super(props);
this.state = {
isLogin:false
}
}
// 返回原来的页
toOrigin = ()=>{
// 🚀使用Auth中的login,传入一个回调函数callback
Auth.login(()=>{
this.setState({
isLogin:true
})
})
}
render() {
console.log(" 🚀 PrivateRoute传递过来的值",this.props.location.state);
// 🚀 解构下之前路径传递过来的参数到path中,然后Redirect重定向回去
let path = this.props.location.state.from.pathname;
let {isLogin} = this.state;
if(isLogin){
return <Redirect to={path}/>
}
else{
return (
<div>
<p>请先登录</p>
<button onClick={this.toOrigin}>登 录</button>
</div>
);
}
}
}
export default Login;