最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React路由監(jiān)聽/跳轉(zhuǎn)/守衛(wèi)的完整指南

 更新時(shí)間:2026年03月24日 08:26:48   作者:發(fā)現(xiàn)一只大呆瓜  
React Router 是 React 單頁應(yīng)用的核心路由庫,除了基礎(chǔ)的路由配置,日常開發(fā)中還會(huì)高頻用到路由監(jiān)聽、編程式跳轉(zhuǎn)、路由守衛(wèi)等進(jìn)階功能,本文從實(shí)戰(zhàn)角度拆解這三大核心能力,需要的朋友可以參考下

前言

React Router 是 React 單頁應(yīng)用的核心路由庫,除了基礎(chǔ)的路由配置,日常開發(fā)中還會(huì)高頻用到路由監(jiān)聽、編程式跳轉(zhuǎn)、路由守衛(wèi)等進(jìn)階功能。本文從實(shí)戰(zhàn)角度拆解這三大核心能力,涵蓋實(shí)現(xiàn)方式、場(chǎng)景對(duì)比、避坑要點(diǎn),基于 React Router v6+ 版本(主流穩(wěn)定版)講解,新手也能快速落地!

一、 路由監(jiān)聽:如何捕捉 URL 的變化?

在 React 中,React 監(jiān)聽路由變化的本質(zhì)是監(jiān)聽 URL 相關(guān)屬性(pathname/search/params 等)的變化,觸發(fā)自定義回調(diào)函數(shù)。以下是 3 種常用實(shí)現(xiàn)方式:

1. 核心方案:useLocation+useEffect

這是最通用的監(jiān)聽方式。通過 useLocation 獲取當(dāng)前路由完整信息(pathname/search/state 等),結(jié)合 useEffect 監(jiān)聽 location 對(duì)象變化,觸發(fā)回調(diào)函數(shù)。

import { useLocation } from 'react-router-dom';
import { useEffect } from 'react';

const App = () => {
  const location = useLocation();

  useEffect(() => {
    // 每次路由切換時(shí)執(zhí)行
    console.log('當(dāng)前路徑:', location.pathname);
    console.log('搜索參數(shù):', location.search);
  }, [location]); 
};

2. 精準(zhǔn)監(jiān)聽:useParams與useSearchParams

如果你只關(guān)心某個(gè)特定的動(dòng)態(tài)參數(shù)(如 id),直接監(jiān)聽參數(shù)對(duì)象會(huì)更高效。

  • useParams:監(jiān)聽動(dòng)態(tài)路由參數(shù)(如 /user/:id 中的 id);
  • useSearchParams:監(jiān)聽 URL 搜索參數(shù)(如 ?page=1&size=10);
  • 適用場(chǎng)景:
    • 僅關(guān)注動(dòng)態(tài)路由參數(shù)或搜索參數(shù)變化的場(chǎng)景(如詳情頁 ID 切換、列表頁分頁參數(shù)變化)。

3.監(jiān)聽原生路由事件(不推薦)

  • 通過 window.addEventListener 監(jiān)聽 popstate(History 模式)或 hashchange(Hash 模式)事件,直接捕獲 URL 變化。
  • 缺點(diǎn):React Router 已封裝原生事件,手動(dòng)監(jiān)聽易出現(xiàn)重復(fù)觸發(fā)、狀態(tài)不一致問題,僅建議特殊場(chǎng)景(如兼容老代碼)使用。

二、 路由跳轉(zhuǎn)

React Router 提供多種跳轉(zhuǎn)方式,適配「點(diǎn)擊跳轉(zhuǎn)」「編程式跳轉(zhuǎn)」「導(dǎo)航欄高亮」等不同場(chǎng)景:

1. 聲明式導(dǎo)航:<Link>與<NavLink>(最常用)

<Link> :基礎(chǔ)跳轉(zhuǎn),React Router 核心跳轉(zhuǎn)組件,替代原生 <a> 標(biāo)簽(避免頁面刷新),核心屬性如下:

  • to:必傳,目標(biāo)路徑(支持字符串 / 對(duì)象格式);
  • replace:默認(rèn) false(新增歷史記錄),true 則替換當(dāng)前記錄(跳轉(zhuǎn)后無法回退);
  • state:傳遞自定義狀態(tài)(不顯示在 URL 中,通過 useLocation().state 獲?。?/li>

<NavLink> :專為導(dǎo)航欄設(shè)計(jì),新增激活狀態(tài)相關(guān)配置,適合導(dǎo)航欄場(chǎng)景:

  • isActive:可根據(jù)激活狀態(tài)動(dòng)態(tài)設(shè)置樣式類名。
  • end:精準(zhǔn)匹配模式,防止 / 匹配到所有子路由(如 /home 不匹配 /home/detail)。

2. 編程式導(dǎo)航:useNavigate

適用于點(diǎn)擊按鈕后的邏輯處理或異步請(qǐng)求后的跳轉(zhuǎn),通過 useNavigate Hook 獲取導(dǎo)航函數(shù),實(shí)現(xiàn)非點(diǎn)擊觸發(fā)的跳轉(zhuǎn)(如接口請(qǐng)求后、條件判斷后)。

const navigate = useNavigate();

// 基礎(chǔ)跳轉(zhuǎn),帶狀態(tài)
navigate('/profile', { replace: true, state: { from: 'home' } });

// 歷史記錄操作
navigate(-1); // 后退一步

三、 路由守衛(wèi):在 React 中如何“攔截”?

Vue 有原生的 beforeEach/afterEach 路由守衛(wèi),但 React Router 無專屬 API,核心通過監(jiān)聽路由 + 條件判斷實(shí)現(xiàn),分為 3 類場(chǎng)景:

1. 全局路由守衛(wèi)

實(shí)現(xiàn)邏輯

在路由根組件(如 App.jsx)中監(jiān)聽 location 變化,執(zhí)行全局校驗(yàn)(如登錄狀態(tài)、白名單),攔截非法跳轉(zhuǎn)。

實(shí)戰(zhàn)代碼

import { useLocation, useNavigate, useEffect } from 'react-router-dom';
import { isLogin } from '@/utils/auth'; // 自定義登錄校驗(yàn)函數(shù)

// 全局路由守衛(wèi)組件
const GlobalRouterGuard = () => {
  const location = useLocation();
  const navigate = useNavigate();
  // 無需登錄的白名單路由
  const whiteList = ['/login', '/register'];

  useEffect(() => {
    // 未登錄且不在白名單 → 跳轉(zhuǎn)到登錄頁
    if (!isLogin() && !whiteList.includes(location.pathname)) {
      navigate('/login', { 
        replace: true,
        state: { from: location.pathname } // 記錄來源路徑,登錄后跳轉(zhuǎn)回去
      });
    }
  }, [location.pathname, navigate]);

  return null; // 守衛(wèi)組件無需渲染 DOM
};

// 在根路由中引入
// <BrowserRouter>
//   <GlobalRouterGuard />
//   <Routes>...</Routes>
// </BrowserRouter>

2. 組件內(nèi)路由守衛(wèi)

實(shí)現(xiàn)邏輯

在組件內(nèi)通過 useEffect 實(shí)現(xiàn)進(jìn)入守衛(wèi)(組件掛載時(shí)校驗(yàn)),通過 useEffect 的返回函數(shù)實(shí)現(xiàn)離開守衛(wèi)(組件卸載時(shí)執(zhí)行)。

實(shí)戰(zhàn)代碼

import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { hasPermission } from '@/utils/permission'; // 自定義權(quán)限校驗(yàn)

const UserDetail = () => {
  const navigate = useNavigate();

  // 進(jìn)入守衛(wèi):組件掛載時(shí)校驗(yàn)權(quán)限
  useEffect(() => {
    if (!hasPermission('user:view')) {
      navigate('/403', { replace: true });
    }
  }, [navigate]);

  // 離開守衛(wèi):組件卸載時(shí)執(zhí)行(如保存表單、提示未提交內(nèi)容)
  useEffect(() => {
    return () => {
      console.log('離開用戶詳情頁,執(zhí)行清理邏輯');
      // 業(yè)務(wù)邏輯:保存草稿、關(guān)閉WebSocket等
    };
  }, []);

  return <div>用戶詳情頁</div>;
};

3. 路由獨(dú)享守衛(wèi)

  • 概念: 不影響全局其他路由,只針對(duì)這一個(gè)頁面(或這一組頁面)進(jìn)行特殊的準(zhǔn)入檢查。 例如整個(gè)應(yīng)用都可以訪問,但只有/admin頁面需要檢查管理員權(quán)限
  • 實(shí)現(xiàn)”先創(chuàng)建一個(gè)守衛(wèi)組件AdminGuard,這個(gè)組件專門負(fù)責(zé)檢查當(dāng)前用戶是不是管理員,然后將需要單獨(dú)檢查的Admin路由套在這個(gè)守衛(wèi)組件AdminGuard里面

實(shí)戰(zhàn)代碼:

// 守衛(wèi)組件:AdminGuard.jsx
import { useNavigate } from 'react-router-dom';
import { isAdmin } from '@/utils/auth';

const AdminGuard = ({ children }) => {
  const navigate = useNavigate();
  
  // 管理員權(quán)限校驗(yàn)
  if (!isAdmin()) {
    navigate('/403', { replace: true });
    return null;
  }

  // 權(quán)限通過,渲染子組件
  return children;
};

// 路由配置中使用
import { Routes, Route } from 'react-router-dom';
import SettingsPage from '@/pages/Settings';

const RouterConfig = () => {
  return (
    <Routes>
      {/* 獨(dú)享守衛(wèi):僅 /settings 路由觸發(fā)管理員校驗(yàn) */}
      <Route 
        path="/settings" 
        element={
          <AdminGuard>
            <SettingsPage />
          </AdminGuard>
        } 
      />
    </Routes>
  );
};

4.擴(kuò)展:離開時(shí)的路由攔截(useBlocker)

useBlocker 是 React Router v6 新增 Hook,用于攔截所有路由跳轉(zhuǎn)行為(包括 <Link>、navigate、瀏覽器前進(jìn) / 后退)。

import { useBlocker } from 'react-router-dom';

// blockerFn:返回 true 攔截跳轉(zhuǎn),false 放行
// when:是否啟用攔截(可選,默認(rèn) true)
useBlocker((tx) => {
  console.log('即將跳轉(zhuǎn)到:', tx.location.pathname);
  return true; // 攔截跳轉(zhuǎn)
}, when);

實(shí)戰(zhàn)場(chǎng)景:表單未提交攔截

import { useBlocker } from 'react-router-dom';

const FormPage = () => {
  const [formDirty, setFormDirty] = useState(false); // 表單是否修改

  // 表單未提交時(shí)攔截跳轉(zhuǎn)
  useBlocker((tx) => {
    if (formDirty) {
      const confirm = window.confirm('表單內(nèi)容未保存,是否確認(rèn)離開?');
      return !confirm; // 點(diǎn)擊取消 → 攔截(返回 true)
    }
    return false; // 放行
  }, formDirty); // 僅表單修改時(shí)啟用攔截

  return (
    <form onChange={() => setFormDirty(true)}>
      <input type="text" placeholder="輸入內(nèi)容..." />
    </form>
  );
};

四、 總結(jié)與最佳實(shí)踐

  1. 優(yōu)先使用原生 Link:對(duì)于簡單的跳轉(zhuǎn),<Link> 的性能和 SEO 優(yōu)于 useNavigate。
  2. 善用 State 傳參:如果不想 URL 變得太長,利用 location.state 傳遞對(duì)象是最佳選擇。
  3. 守衛(wèi)邏輯模塊化:不要在 App.js 里寫一堆 if-else,將權(quán)限校驗(yàn)封裝成獨(dú)立的 Guard 組件。

以上就是React路由監(jiān)聽/跳轉(zhuǎn)/守衛(wèi)的完整指南的詳細(xì)內(nèi)容,更多關(guān)于React路由監(jiān)聽/跳轉(zhuǎn)/守衛(wèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React拖拽調(diào)整大小的組件

    React拖拽調(diào)整大小的組件

    這篇文章主要為大家詳細(xì)介紹了React拖拽調(diào)整大小的組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 詳解在create-react-app使用less與antd按需加載

    詳解在create-react-app使用less與antd按需加載

    這篇文章主要介紹了詳解在create-react-app使用less與antd按需加載,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • 詳解React 服務(wù)端渲染方案完美的解決方案

    詳解React 服務(wù)端渲染方案完美的解決方案

    這篇文章主要介紹了詳解React 服務(wù)端渲染方案完美的解決方案,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • 如何在React中通過URL預(yù)覽Excel文件

    如何在React中通過URL預(yù)覽Excel文件

    這篇文章主要為大家詳細(xì)介紹了如何在React中通過URL預(yù)覽Excel文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • React在組件中如何監(jiān)聽redux中state狀態(tài)的改變

    React在組件中如何監(jiān)聽redux中state狀態(tài)的改變

    這篇文章主要介紹了React在組件中如何監(jiān)聽redux中state狀態(tài)的改變,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • React 三大屬性之state的使用詳解

    React 三大屬性之state的使用詳解

    這篇文章主要介紹了React 三大屬性之state的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下
    2021-04-04
  • 詳解如何使用React Hooks請(qǐng)求數(shù)據(jù)并渲染

    詳解如何使用React Hooks請(qǐng)求數(shù)據(jù)并渲染

    這篇文章主要介紹了如何使用React Hooks請(qǐng)求數(shù)據(jù)并渲染,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • React組件化條件渲染的實(shí)現(xiàn)

    React組件化條件渲染的實(shí)現(xiàn)

    本文主要介紹了React組件化條件渲染的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • react native之ScrollView下拉刷新效果

    react native之ScrollView下拉刷新效果

    這篇文章主要為大家詳細(xì)介紹了react native之ScrollView下拉刷新效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • React.InputHTMLAttributes實(shí)踐和注意事項(xiàng)

    React.InputHTMLAttributes實(shí)踐和注意事項(xiàng)

    文章討論了如何在封裝組件中使用React.InputHTMLAttributes,以及如何通過 {...inputProps} 動(dòng)態(tài)傳遞屬性,最后,文章總結(jié)了使用React.InputHTMLAttributes的最佳實(shí)踐和注意事項(xiàng),感興趣的朋友一起看看吧
    2024-11-11

最新評(píng)論

吉隆县| 宁国市| 平定县| 海原县| 图们市| 通榆县| 张北县| 永善县| 黄冈市| 筠连县| 嵊州市| 襄垣县| 黄浦区| 堆龙德庆县| 根河市| 泗水县| 宁晋县| 醴陵市| 曲靖市| 开封市| 黔江区| 永和县| 长春市| 观塘区| 普兰店市| 博湖县| 南漳县| 千阳县| 屏南县| 彭州市| 沈阳市| 延津县| 黔西县| 景宁| 高碑店市| 望城县| 霍山县| 铜鼓县| 临清市| 肇庆市| 屏东市|