React全家桶-04-react路由守卫的实现

779 阅读2分钟

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;