React 封装路由鉴权组件

一. 封装AuthRoute鉴权路由组件

  1. 创建组件 AuthRoute 并导出
  2. AuthRoute组件中返回Route组件(在Route基础上做了一层包装,用于实现自定义功能)
  3. Route组件添加render方法,指定该组件要渲染的内容(类似于 component 属性)
  4. 在render方法中,判断用户是否登录
  5. 如果登录了,就渲染当前组件(通过参数component获取到要渲染的组件,因为组件都是大写开头,因此需要重命名)
  6. 如果没有登录,就重定向到登录页面,并指定登录成功后要跳转到的页面路径
  7. AuthRoute 组件接收到的props原样传递给Route组件(保证与Route 组件使用的方式相同)
  8. 使用AuthRoute 组件配置的路由规则,验证能否实现页面的登录访问控制
import React from 'react'
import { Route, Redirect } from 'react-router-dom'

// 使用方法: <AuthRoute path="..." component={...} 其他属性名="其他属性值" />
const AuthRoute = ({ component: Component, ...rest }) => {
    return (
        // rest属性存放 path="..."和其他属性名等属性
        <Route {...rest} render={props => {

            const isLogin = '判断用户是否登录'
            
            if (isLogin) {
            
                // 已经登录,渲染传入的Component组件,将props传递给组件,组件中才能获取到路由的相关信息
                return <Component {...props} />
            } else {
            
                // 未登录,渲染重定向组件,通过to属性指定跳转的路由信息
                return <Redirect to={{
                	// 指定重定向的url
                    pathname: '/login',
                    state: {
                        /*
                        	未登录时,要访问的页面url,我们可以在登录页面获取到该url,当登录成功之后,可以直接跳转到该url
                        	之所以指定属性名为from,是因为我们在Login组件中配置了要使用🤪props.location.state.from🤪
						*/ 
                        from: props.location
                    }
                }} />
            }

        }} />
    )
}

export default AuthRoute

二. 使用自定义鉴权路由组件

import React from "react";
// 导入路由组件
import { BrowserRouter, Redirect, Route } from 'react-router-dom'

// 导入自定义的路由鉴权组件
import AuthRoute from './components/AuthRoute' 

// 导入登录组件
import Login from './pages/Login'

// 导入登录后才能访问的组件
import Rent from './pages/Rent'
import RentAdd from './pages/Rent/Add'

function App() {
  return (
    // 要想使用路由,需要使用Router包裹根组件
    <BrowserRouter>
    	<div className="App">
     
          {/* 登录组件的路由地址 */}
          <Route path="/login" component={Login}></Route>

          {/* ⏹AuthRoute自定义鉴权路由组件,只有登录后才能访问,未登录访问会跳转到/login页面中 */}
          <AuthRoute exact path='/rent' component={Rent} />
          <AuthRoute path='/rent/add' component={RentAdd} />
        </div>
    </BrowserRouter>
  );
}

export default App;

三.登录组件中的处理

  • 如果是主动点击登录按钮访问的login组件,当登录成功之后,会跳转到前页面
  • 如果是重定向到login组件,当登录成功之后,会跳转到重定向之前的页面
import React, { Component } from 'react'

// 导入withFormik
import { withFormik } from 'formik'

class Login extends Component {

  render() {

    return (
      // 省略...
    )
  }
}

/*
  使用withFormik高阶组件包装Login组件,为Login组件提供属性和方法
  返回的是被高阶组件包裹之后的Login组件
*/ 
Login = withFormik({
  
  // 省略...

  // 为表单提供提交事件(当表单提交的时候,就会触发该函数)
  handleSubmit: async (values, { props }) => {
    
    // 解构出用户输入的账号和密码
    const { username, password } = values;

    // 调用登录的接口
    const res = await axios.post('/user/login', {
      username,
      password
    });

    // 解构后端返回的值
    const { status, body } = res.data;
    
    // 登录成功
    if (status === 200) {
      // 将token值保存到浏览器中
      localStorage.setItem('项目token名称', body.token);
      
      // 当props.location.state为空时,说明是直接进入的登录页面,登录成功之后返回上一个页面即可
      if (!props.location.state) {
        /*
          返回上一个页面
          注意: 无法在该方法汇总通过this.props来获取到路由信息(因为this指向当前回调函数,并不指向该组件)
          通过handleSubmit方法的第二个参数中解构出props来使用props
        */ 
        props.history.go(-1);
      } else {
        /*
          ⏹如果props.location.state不为空,说明未登录却访问了登录之后才能看的页面,然后被重定向到Login登录页面
          这个时候props.location.state中会含有原先页面的url(我们在鉴权组件AuthRoute中进行了配置)
          
          ⏹props.history.replace()和props.history.push()的区别
          ※rent页面是登录之后才能访问的页面
          当我们从首页点击右上角地图图标的时候,访问顺序如下 首页 -> Login登录页面 -> rent页面
          当我们进入rent页面之后,点击左上角的返回按钮的时候
          1. 如果是props.history.push()的情况下,访问路径被记录在这样的数组里 ['home', 'login', 'rent']
              所以当我们在Rent页面点击返回上一个页面的时候,会找到第二个元素 login, 跳转到Login登录页面
              我们已经登录成功了,所以不需要返回login页面
          2. 如果是props.history.replace()的情况下,当我们访问到Login组件的时候,访问的路径被记录在这样的数组里
              ['home', 'login'],我们登录成功之后,进入rent页面,因为使用的是replace(),所以 /login 会被替换为 /rent
              也就说数组变成了['home', 'rent'],所以在rent页面返回前一个页面的时候,跳转到的是 /home 而不是 /login
        */
        props.history.replace(props.location.state.from.pathname);
        // ⏹因为我们在props.location.state.from中使用了from,因此rent组件中也要配置🤪from🤪
      }
    }
  }
})(Login)

// 注意: 此处返回的是被高阶组件包装后的Login组件
export default Login

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值