路由跳转和路由参数

路由跳转

路由跳转的方式分为标签跳转和编程式跳转。

标签跳转

使用NavLink组件或者Link组件,定义路由组件跳转。

Link组件

Link组件中最重要的属性to,用于设置跳转到的路径。

js 复制代码
// main.jsx
import { createRoot } from 'react-dom/client' // 用于渲染页面的
import React from 'react' // 用于创建组件的
import { BrowserRouter as Router } from 'react-router-dom' // 引入路由
import App from './App.jsx'

createRoot(document.getElementById('root')).render(
    <Router>
        <App />
    </Router>
)
js 复制代码
// App.jsx
import React from "react"
import { Routes, Route, Link } from "react-router-dom"
import Home from "./Home.jsx"
import Shop from "./Shop.jsx"
export default function App() {
  return (
    <>
      <div>
        <Link to='/home'>首页</Link>
        <Link to='/shop'>商品</Link>
      </div>
      <Routes>
        <Route path="/home" element={<Home></Home>}></Route>
        <Route path="/shop" element={<Shop></Shop>}></Route>
      </Routes>
    </>
  )
}

NavLink组件会在属性to匹配成功的那个NavLink组件上添加一个动态的active类名,我们可以根据这个类名设置一些样式。

css 复制代码
/* App.css */
.active {
    color: red;
}
js 复制代码
// App.jsx
import React from "react"
import "./App.css"
import { Routes, Route, NavLink } from "react-router-dom"
import Home from "./Home.jsx"
import Shop from "./Shop.jsx"
export default function App() {
  return (
    <>
      <div>
        <NavLink to='/home'>首页</NavLink>
        <NavLink to='/shop'>商品</NavLink>
      </div>
      <Routes>
        <Route path="/home" element={<Home></Home>}></Route>
        <Route path="/shop" element={<Shop></Shop>}></Route>
      </Routes>
    </>
  )
}

NavLink组件和Link组件相当于超连接,它和a标签的区别是,NavLink组件和Link组件不会刷新整个网站,只是切换路由页面渲染不同组件。而a标签会再次重新请求整个网站然后刷新网页,a标签多用于和外部网站建立链接。

js 复制代码
// App.jsx
import React from "react"
import { Routes, Route, Link } from "react-router-dom"
import Home from "./Home.jsx"
import Shop from "./Shop.jsx"
export default function App() {
  return (
    <>
      <Link to="/home">首页</Link>
      <a href="/shop">商品</a>
      <Routes>
        <Route path="/home" element={<Home></Home>}></Route>
        <Route path="/shop" element={<Shop></Shop>}></Route>
      </Routes>
    </>
  )
}

上面动图可以清晰看到点击a标签进行跳转时,浏览器的刷新图标运行了让页面重新刷新了。而Link组件并没有让浏览器的刷新图标运行。

编程式跳转

使用useNavigatehook进行编程式跳转,useNavigate 返回一个 navigate 函数,可以用来进行路由跳转和监听路由变化。

navigate 函数接受两个参数:

  • to (字符串或数字):要跳转的目标路径或者历史记录栈中的位置。如果提供的是一个字符串,那么它会被当作一个新的路径;如果是数字,则表示在历史记录栈中移动多少步,例如-1表示回退上一步。
  • options (对象):可选参数,包含以下属性:
    • replace (布尔值,默认为 false): 如果设置为 true,则新的位置会替换当前的历史记录条目而不是添加新的条目。
    • state (任意类型):可以用来传递状态信息到目标页面。这个状态可以通过 useLocation Hook 在目标页面获取。

字符串路径跳转

js 复制代码
// App.jsx
import React from "react"
import { Routes, Route, useNavigate } from "react-router-dom"
import Home from "./Home.jsx"
import Shop from "./Shop.jsx"
export default function App() {
  const navigate = useNavigate();
  const goToPage = (val) => {
    navigate(`${val}`)
  }
  return (
    <>
      <div>
        <button onClick={() => {goToPage('home')}}>首页</button>
        <button onClick={() => {goToPage('shop')}}>商品</button>
      </div>
      <Routes>
        <Route path="/home" element={<Home></Home>}></Route>
        <Route path="/shop" element={<Shop></Shop>}></Route>
      </Routes>
    </>
  )
}

带状态的跳转

假设有两个页面:Home 和 Shop。从 Home 页面跳转到 Shop 页面时,需要传递一些商品信息。

js 复制代码
// App.jsx
import React from "react"
import { Routes, Route, useNavigate } from "react-router-dom"
import Home from "./Home.jsx"
import Shop from "./Shop.jsx"
export default function App() {
  const navigate = useNavigate();
  const goToPage = (val) => {
    navigate(`${val}`)
  }
  return (
    <>
      <div>
        <button onClick={() => {goToPage('home')}}>首页</button>
        <button onClick={() => {goToPage('shop')}}>商品</button>
      </div>
      <Routes>
        <Route path="/home" element={<Home></Home>}></Route>
        <Route path="/shop" element={<Shop></Shop>}></Route>
      </Routes>
    </>
  )
}

在 Home 组件中,使用 useNavigate 进行带状态的路由跳转:

js 复制代码
// Home.jsx
import React from "react";
import { useNavigate } from 'react-router-dom'
const Home = (props) => {
    const navigate = useNavigate();

    const handleNavigate = () => {
        const shop = {
            type: '专辑',
            name: '启示录',
            describe: '《启示录》是邓紫棋于2022年8月9日发行的音乐专辑,共收录14首歌曲,由邓紫棋担任制作人 。2022年,该专辑获得微博视界大会突破创新音乐连续剧奖 、亚洲流行音乐大奖年度最佳专辑奖。2023年,邓紫棋凭借该专辑获得浪潮音乐大赏最佳女歌手奖、年度专辑奖'
        };
        navigate('/shop', { state: { shop } });
    };
    return (
        <>
            <h1>首页</h1>
            <p>这是首页的数据</p>
            <button onClick={handleNavigate}>前往商品页查看详情</button>
        </>
    )
}
export default Home

Home 组件:

  1. 导入 useNavigate 并在组件内部调用它来获取 navigate 函数。
  2. handleNavigate 函数中,创建一个 shop 对象并将其作为状态传递给 navigate 函数。
  3. 当按钮被点击时,触发 handleNavigate 函数,进行路由跳转。

在 Shop 组件中,使用 useLocation 获取传递的状态信息:

js 复制代码
// Son.jsx
import React from "react"
import { useLocation } from 'react-router-dom';
const Shop = (props) => {
    const location = useLocation();
    const { shop } = location.state || {};
    return (
        <>
            <h1>商品</h1>
            <p>这是商品页的数据</p>
            {shop ? (
                <div>
                    <p>商品种类: {shop.type}</p>
                    <p>商品名称: {shop.name}</p>
                    <p>商品信息: {shop.describe}</p>
                </div>
            ) : (
                <p>暂时没有商品数据</p>
            )}
        </>
    )
}
export default Shop

Shop 组件:

  1. 导入 useLocation 并在组件内部调用它来获取当前路由的位置信息。
  2. location.state 中提取传递的 shop 对象。
  3. 如果 shop 存在,则显示商品的详细信息;否则显示提示信息。

回退至上一页

js 复制代码
navigate(-1);

替换当前历史记录条目

js 复制代码
navigate('/shop', { replace: true });

当在一个网站中使用导航时,浏览器会记录访问过的每个页面。这些记录组成了一个历史记录栈。每次点击链接或通过编程方式跳转到一个新的页面时,浏览器会在历史记录栈中添加一个新的条目。这样,当点击浏览器的"后退"按钮时,浏览器会回到上一个记录的位置。

替换当前历史记录条目:

默认情况下,navigate 函数会在历史记录栈中添加一个新的条目。这意味着如果从页面 A 跳转到页面 B,然后再从页面 B 跳转到页面 C,历史记录栈会是这样的:

  1. 页面 A
  2. 页面 B
  3. 页面 C

如果现在点击浏览器的"后退"按钮,就会从页面 C 回到页面 B。

但是,如果设置了 replace: true,那么浏览器不会添加新的历史记录条目,而是会替换当前的历史记录条目。这意味着如果从页面 A 跳转到页面 B,然后从页面 B 跳转到页面 C 且从页面 B跳转到页面 C时设置了 replace: true,历史记录栈会是这样的:

  1. 页面 A
  2. 页面 C

在这种情况下,如果点击浏览器的"后退"按钮,你会直接从页面 C 回到页面 A,而不会经过页面 B。因为页面 B在跳转到页面 C时,历史记录栈的页面B被替换成了页面C。

路由参数

有三种常见的方法可以实现路由之间的参数传递:

  • search传参:查询字符串参数
  • params传参:动态路由参数
  • state传参:状态传递参数

查询字符串参数以及获取参数方法

查询字符串参数适用于需要在URL中传递额外的、可选的参数。它是将参数拼接在网址的querystring中。

优点:刷新页面后参数不丢失

缺点:只能传字符串,传值过多URL会变得很长,获取参数需要自己解析字符串。

示例

假设在Home页面进行搜索然后在Shop页面显示搜索的商品信息,URL格式为 /search?query=启示录

js 复制代码
// App.jsx
import React from "react"
import { Routes, Route, useNavigate } from "react-router-dom"
import Home from "./Home.jsx"
import Shop from "./Shop.jsx"
export default function App() {
  const navigate = useNavigate();
  const goToPage = (val) => {
    navigate(`${val}`)
  }
  return (
    <>
      <div>
        <button onClick={() => {goToPage('home')}}>首页</button>
        <button onClick={() => {goToPage('shop')}}>商品</button>
      </div>
      <Routes>
        <Route path="/home" element={<Home></Home>}></Route>
        <Route path="/shop" element={<Shop></Shop>}></Route>
      </Routes>
    </>
  )
}

在Home组件路由跳转进行传参:

js 复制代码
// Home.jsx
import React, { useState } from "react";
import { useNavigate } from 'react-router-dom'
const Home = (props) => {
    const navigate = useNavigate();
    let [query, setQuery] = useState("");
    const handleSubmit = (e) => {
        // 阻止表单提交按钮的默认事件
        e.preventDefault();
        navigate(`/shop?query=${query}`);
        // navigate({ pathname: "/shop", search: `query=${query}` });
    };
    return (
        <>
            <h1>首页</h1>
            <p>这是首页的数据</p>
            <form onSubmit={handleSubmit}>
                <input
                    type="text"
                    value={query}
                    onChange={(e) => setQuery(e.target.value)}
                    placeholder="请输入关键字"
                />
                <button type="submit">搜索</button>
            </form>
        </>
    )
}
export default Home

在Shop组件使用 useLocation 获取传递的参数:

js 复制代码
// Shop.jsx
import React from "react"
import { useLocation } from 'react-router-dom';
const Shop = (props) => {
    // 接受search参数
    const location = useLocation();
    console.log(location, "location");
    // 需要手动解析search参数
    const { search } = location;
    const shop = {
        type: '专辑',
        name: '启示录',
        describe: '《启示录》是邓紫棋于2022年8月9日发行的音乐专辑,共收录14首歌曲,由邓紫棋担任制作人 。2022年,该专辑获得微博视界大会突破创新音乐连续剧奖 、亚洲流行音乐大奖年度最佳专辑奖。2023年,邓紫棋凭借该专辑获得浪潮音乐大赏最佳女歌手奖、年度专辑奖'
    };
    return (
        <>
            <h1>商品</h1>
            <p>这是商品页的数据</p>
            {search ? (
                <div>
                    <p>商品种类: {shop.type}</p>
                    <p>商品名称: {shop.name}</p>
                    <p>商品信息: {shop.describe}</p>
                </div>
            ) : (
                <p>暂时没有商品数据</p>
            )}
        </>
    )
}
export default Shop

loaction对象的返回值如下:

注意:当使用对象用pathname跳转传参时不能在pathname后面直接拼接参数会报错,必须使用search属性且属性值只能是字符串,当传参需要变量动态取值只能使用反引号的模板字符串,不能是对象。

js 复制代码
navgite({pathname:'/shop?query=89'}); // 错误写法
navgite({pathname:'/shop',search:'gid=89'}); // 正确写法
navgite('/shop?gid=89'); // 正确写法
let gid=89;
navgite(`/shop?gid=${gid}`); // 正确写法
navigate({ pathname: "/shop", search: `gid=${gid}` }); // 正确写法

动态路由参数以及参数获取方法

动态路由参数适用于需要在URL中传递参数的情况,它是将参数拼接在网址的pathname中。

优点:刷新页面,参数不丢失

缺点:只能传字符串,传值过多URL会变得很长;参数必须在路由上配置

js 复制代码
// 1.设置可传参数
<Route path='/center/:name/:uid' element={<Suspense><Usercenter /></Suspense>}></Route>
// 2.传参
navigate({pathname:`/center/utc_20090729/6`});
或
<Link to={{pathname:`/center/utc_19890530/7`}}>跳转到个人中心</Link>
// 3.接收参数
import {useParams} from 'react-router-dom';
let person = useParams();
console.log(person.name,person.uid)

示例

假设在Home组件中点击按钮传入商品的id跳转到商品详情页面,URL格式为 /shop/:id,其中 :id 是动态部分。

设置可传参数:

js 复制代码
// App.jsx
import React from "react"
import { Routes, Route, useNavigate } from "react-router-dom"
import Home from "./Home.jsx"
import Shop from "./Shop.jsx"
export default function App() {
  const navigate = useNavigate();
  const goToPage = (val) => {
    navigate(`${val}`)
  }
  return (
    <>
      <div>
        <button onClick={() => {goToPage('home')}}>首页</button>
      </div>
      <Routes>
        <Route path="/home" element={<Home></Home>}></Route>
        {/*设置可传参数*/}
        <Route path="/shop/:id" element={<Shop></Shop>}></Route>
      </Routes>
    </>
  )
}

在Home组件中传参:

js 复制代码
import React from "react";
import { useNavigate } from 'react-router-dom'
const Home = (props) => {
    const navigate = useNavigate();
    const shops = [
        { id: 1, name: '启示录' },
        { id: 2, name: '摩天动物园' },
        { id: 3, name: '新的心跳' }
    ];
    const goToDetail = (val) => {
        navigate({ pathname: `/shop/${val}` })
    }
    return (
        <>
            <h1>首页</h1>
            <p>这是首页的数据</p>
            {shops.map(item => {
                return (
                    <div key={item.id} onClick={() => {goToDetail(item.id)}}>{item.name}</div>
                )
            })}
        </>
    )
}
export default Home

在Shop组件中使用 useParams接受参数:

js 复制代码
import React from "react"
import { useParams } from 'react-router-dom';
const Shop = (props) => {
    // 接受params参数
    const params = useParams();
    console.log(params, "params");
    // 需要手动解析search参数
    const { id } = params;
    let shop = {}
    // 模拟请求数据
    if (id == 1) {
        shop = {
            type: '专辑',
            name: '启示录',
            describe: '《启示录》是邓紫棋于2022年8月9日发行的音乐专辑,共收录14首歌曲,由邓紫棋担任制作人 。2022年,该专辑获得微博视界大会突破创新音乐连续剧奖 、亚洲流行音乐大奖年度最佳专辑奖。2023年,邓紫棋凭借该专辑获得浪潮音乐大赏最佳女歌手奖、年度专辑奖'
        };
    } else if (id == 2) {
        shop = {
            type: '专辑',
            name: '摩天动物园',
            describe: '《摩天动物园》是邓紫棋于2019年12月27日发行的音乐专辑,共收录13首歌曲,由邓紫棋担任制作人。2020年,该专辑获得第31届台湾金曲奖"评审团奖"、第43届十大中文金曲"最佳中文唱片奖" 、2020hito流行音乐奖"亚洲传媒推崇大奖" 、2019年度流行音乐全金榜"年度最佳专辑奖"'
        };
    } else if (id == 3) {
        shop = {
            type: '专辑',
            name: '新的心跳',
            describe: '新的心跳》是邓紫棋于2015年11月6日发行的音乐专辑,共收录10首歌曲。2016年,邓紫棋凭该专辑获得第6届全球流行音乐金榜"年度最佳女歌手奖" ;该专辑则获得第10届音乐盛典咪咕汇"年度最佳国语专辑奖"、IFPI香港唱片销量大奖"全年最高销量国语唱片奖",并提名第27届台湾金曲奖"最佳演唱录音专辑奖"。'
        };
    }
    return (
        <>
            <h1>商品</h1>
            <p>这是商品页的数据</p>
            <div>
                <p>商品种类: {shop.type}</p>
                <p>商品名称: {shop.name}</p>
                <p>商品信息: {shop.describe}</p>
            </div>
        </>
    )
}
export default Shop

状态传参

state状态传参适用于不需要在URL中显示参数的情况,可以通过 useNavigatestate 属性传递。

优点:可以传对象,参数不会拼接在网址中,可以用于传不用给用户看见的参数

缺点: <HashRouter>刷新页面,参数丢失

官方建议使用<BrowserRouter><BrowserRouter>页面刷新参数也不会丢失。

示例

假设有一个登录页面,登录成功后跳转到首页并传递用户信息。

js 复制代码
// App.jsx
import React from "react"
import { Routes, Route } from "react-router-dom"
import Login from "./Login.jsx"
import Home from "./Home.jsx"
export default function App() {
  return (
    <>
      <Routes>
      <Route path="/" element={<Login />} />
        <Route path="/home" element={<Home></Home>}></Route>
      </Routes>
    </>
  )
}

Login组件传参:

js 复制代码
// Login.jsx
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';

function Login() {
  const [username, setUsername] = useState('');
  const navigate = useNavigate();

  const handleSubmit = (e) => {
    e.preventDefault();
    const user = { username };
    navigate('/home', { state: { user } });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        placeholder="Username"
      />
      <button type="submit">Login</button>
    </form>
  );
}

export default Login;

在Home组件使用useLocation接收参数:

js 复制代码
// Home.jsx
import React from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

function Home() {
    const location = useLocation();
    const { user } = location.state || {};
    console.log(location,"location")
    const navigate = useNavigate();
    const goToPage = (val) => {
        navigate('/')
    }
    return (
        <div>
            <div>
                <button onClick={() => { goToPage('home') }}>前往登录</button>
            </div>
            <h1>Home 页面</h1>
            {user ? (
                <p>Welcome, {user.username}!</p>
            ) : (
                <p>请登录</p>
            )}
        </div>
    );
}

export default Home;

获取参数总结

相关推荐
前端小小王3 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发3 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
不是鱼7 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js
飞翔的渴望10 小时前
antd3升级antd5总结
前端·react.js·ant design
╰つ゛木槿14 小时前
深入了解 React:从入门到高级应用
前端·react.js·前端框架
用户305875848912517 小时前
Connected-react-router核心思路实现
react.js
哑巴语天雨1 天前
React+Vite项目框架
前端·react.js·前端框架
初遇你时动了情1 天前
react 项目打包二级目 使用BrowserRouter 解决页面刷新404 找不到路由
前端·javascript·react.js
码农老起1 天前
掌握 React:组件化开发与性能优化的实战指南
react.js·前端框架
前端没钱1 天前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js