React-Router封装导航守卫

导航守卫

导航守卫:当离开一个页面,进入另一个页面时,触发的事件

history对象的两个属性(listen,block)

  • listen:添加一个监听器,监听地址的变化,当地址发生变化时候,会调用传递的函数

    • 参数:是一个函数,运行时间点:发生在即将跳转到新页面时
      • 函数本身有两个参数;
      • 参数1:location,记录当前地址信息;
      • 参数2:action,一个字符串,表示进入该地址的方式(POP,PUSH,REPLACE)
        • POP:出栈
          a. 通过浏览器后退、前进;
          b. 调用history.go
          c. 调用history.goBack
          d. 调用history.goForward
        • PUSH:入栈
          a. 点击超链接,本质上调用history.push,往栈中加入
        • REPLACE:替换
          • history.replace
  • block:

    • 设置一个阻塞,参数是一个字符串,当页面发生跳转时候,会进入阻塞,并将阻塞消息传递到路由根组件的getUserConfirmation方法的第一个参数
    • 也可以是一个函数,返回一个字符串(函数有两个参数,第一个是location地址信息,第二个是action跳转方式)

路由根组件

  • getUserConfirmation
    • 参数:是一个函数
      • 参数1:history.block传递的阻塞消息
      • 参数2:回调函数,调用该函数并传递true,则表示进入到新页面,否则不做任何操作

代码实例:

封装的RouteGuard顶级路由,有监听和阻塞的方法,代替Router

import React, { Component} from 'react'
import { BrowserRouter as Router, withRouter } from 'react-router-dom'
let preLocation, newLocation, action,unBlock,unListen     //将获取的旧地址,新地址,跳转方式,取消阻塞方法、监听方法保存在全局方便下面RouteGuard组件传递
/**
 * // 创建一个辅助函数,获取history,因为RouteGuard导出引用为最顶级,获取不到history上下文
 */
class _GetHistory extends Component {
    componentDidMount() {   
      // 调用Router上下文的history.block创建阻塞
      unBlock=  this.props.history.block((location, act) => {
            preLocation = this.props.location
            newLocation = location
            action = act
            return ""
          })
      // 调用Router上下文的history.listen创建监听
        unListen=this.props.history.listen((location,action)=>{
            this.props.onChange(this.props.location,location,action)
        })
    }
    componentWillUnmount(){
        unBlock()  //取消阻塞
        unListen()  //组件销毁取消监听
    }
  render() {
   
    return null
  }
}

// 将普通组件用内置的withRouter包装,即可获取Router上下文
const GetHistory = withRouter(_GetHistory)

/**
 * 封装组件,包含Router的所有特性,并且能接收props方法
 */
class RouteGuard extends Component {
  handleConfirm = (msg, callBack) => {
    if (this.props.onBeforeChange) {
      this.props.onBeforeChange(msg, preLocation, newLocation, action, callBack,unBlock)
    }else{
        callBack(true)
    }
  }
  render() {
    return (
      
      <Router getUserConfirmation={this.handleConfirm}>
        <GetHistory onChange={this.props.onChange}/>
        {this.props.children}
      </Router>
    )
  }
}

// 默认导出
export default RouteGuard

使用封装的顶级路由 RouteGuard

import React from 'react'
import { Route, NavLink } from 'react-router-dom'
import RouteGuard from './RouteGuard'

function A() {
  return (
    <div>
      <h1>A组件</h1>
    </div>
  )
}
function B() {
  return (
    <div>
      <h1>B组件</h1>
    </div>
  )
}

export default function App() {
  return (
    <div>
        {/* 需要阻塞就填写属性onBeforeChange */}
      <RouteGuard  //写在最顶级代替Router
        onBeforeChange={(msg, preLocation, newLocation, action, callBack,unBlock) => {
          console.log(
            `阻塞:从${preLocation.pathname}跳转到${newLocation.pathname},跳转方式${action}`
          )
          unBlock()   //阻塞一次就取消阻塞
          callBack(false)  //回调函数为true就不阻塞放行跳转,false就阻止跳转
        }}
        onChange={(preLocation,newlocation,action)=>{
          console.log(`listen:从${preLocation.pathname}${newlocation.pathname}+${action}`);
        }}
      >
        <ul>
          <li>
            <NavLink to="/a">A组件</NavLink>
          </li>
          <li>
            <NavLink to="/b">B组件</NavLink>
          </li>
        </ul>

        <Route exact path="/b" component={B} />
        <Route exact path="/a" component={A} />
      </RouteGuard>
    </div>
  )
}

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Router v6 中,导航守卫被称为“导航器”。导航器是在用户导航到新路由之前执行的函数。 要使用导航器,您需要使用 `useNavigate` 钩子来获取 `navigate` 函数。然后,您可以在需要时调用 `navigate` 函数。导航器函数有一个 `next` 参数,您可以调用 `next()` 来继续导航,或者使用 `next(false)` 来取消导航。 以下是一个示例: ```jsx import { useNavigate } from 'react-router-dom'; function MyComponent() { const navigate = useNavigate(); function beforeNavigate() { // 在这里执行你的导航守卫逻辑 // 如果允许导航,请调用 next() // 如果需要取消导航,请调用 next(false) // 例如,如果用户未登录,请取消导航 if (!isLoggedIn) { return next(false); } // 如果一切正常,继续导航 return next(); } function handleClick() { // 在需要进行导航的地方调用 navigate 函数,并传入要导航到的路径 navigate('/some/path', { beforeNavigate }); } return ( <button onClick={handleClick}>Navigate</button> ); } ``` 在上面的示例中,我们定义了一个名为 `beforeNavigate` 的函数,该函数在用户尝试导航到新路径之前执行。如果用户未登录,则导航将被取消。否则,导航将继续。 我们还定义了一个名为 `handleClick` 的函数,该函数在用户单击按钮时调用 `navigate` 函数来进行导航。我们还将 `beforeNavigate` 函数传递给 `navigate` 函数,以便它可以在导航之前运行我们的导航器逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值