• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

React router V6的基本使用

武飞扬头像
@魏一
帮助1

一:概述

React Router 由三个模块组成,分别是:

  • react-router:路由的核心库,提供核心的组件和钩子。
  • react-router-dom:基于react-router,并添加专门用于DOM的组件,例如:<BrowserRouter / >等。
  • react-router-native:基于react-router,并添加专门用于ReactNative的API,例如:<NativeRouter / >等。

二:router Component

以下描述的是组件,通过使用组件的方式,渲染视图。

1. <BrowserRouter / > 与 <HashRouter / >

使用:在最外层包裹整个应用

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
// react-router-dom 是基于react-router,添加dom所需的Api,所有只需要react-router-dom

const root = ReactDOM.createRoot(document.getElementById("root"));

// BrowserRouter模式,访问地址:http://localhost:8080/home
// 类似vue的history模式
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
)

//hash模式,访问地址:http://locahost:8080/#/home
root.render(
  <React.StrictMode>
    <HashRouter>
      <App />
    </HashRouter>
  </React.StrictMode>
)
学新通

两则对比:

  • hash模式兼容好,history模式是html5提出的,兼容性差(移动端兼容性不错)
  • hash模式下,访问不存在的页面,不需要单独配置nginx。而history模式需要。
  • history模式路由更好看;hash模式带#号,不美观,而且处理描点链接不方便。

以下案例,默认history模式,并只展示核心代码段

2. <Routes / > 与 <Route / >

  • <Route / >必须配合 <Routes / > 使用,被<Routes / >包裹,区别V5 的<Switch / >。
  • <Route / > 相当与if 语句,当其路径与当前url匹配时,则呈现对应的组件。
  • <Route / >可以嵌套使用,需要通过<Outlet / > 组件来渲染子路由;
import { Routes, Route } from "react-router-dom";

<Routes>
  // 1. path 定义路径,element 定义对应渲染组件 
  <Route path="/" element={<Login />} />
  
  <Route path="/layout" element={<WebLayout />}>
  // 2. 嵌套路由需要<Outlet />组件配合使用,该路由访问路径http://localhost:8080/layout/main
    <Route path="main" element={<Home />} />
  </Route>
  
  // 3. Route 也可以不写element属性,展示嵌套路由,对应路由是:/tab/list
  <Route path="/tab">
    <Route path="list" element={<List />} />
  </Route>
  
  // 4. Route 定义replace属性为true的时候,不会产生历史历史记录。默认是false
  <Route path="/list" element={<List>} replace={true} />
        
  // 5. Route 定义Index属性,不需要定义path属性,在子路由里显示该路由页面。
  <Route path="/main" element={<Main />}>
    <Route index element={<Test1 />} />
    
  // 6. 定义动态的路由,访问地址:http://localhost:8080/1
    <Route path=":id" element={<Test2 />} />
  // 访问路径:http://localhost:8080/main/list/1
    <Route path="list/:id" element={<Test2 />} />
    
  </Route>
</Routes>
学新通

3. <Link / > 与 <NavLink / >

必须被<BrowserRouter / > 或 <HashRouter / > 包裹

  • < Link / >类似a标签的,单区别于a标签,是基于a标签封装的组件。 最终<Link / >组件会转为a标签。通常的应用场景类似a标签,不同页面之间的跳转。
  • 有三种传参方式,1. params 2. searchParams 3. state
import { Link } from "react-router-dom";

// to的路由是对象,属性pathName。定义三种传参方式如下:
<Link to={{ pathName: "/" }}></Link>

// params传参  /detail/:id 
<Link to="/detail/1"><Link>
<Link to=`/detail/${id}`><Link>
  
// searchParams传参  /detail?id=1
<Link to="/detail?id=1"></Link>
<Link to=`/detail?id=${id}`></Link>
 
// state 传参
<Link to="/" state={{ id: 1 }}>
  
// replace 为true的时候,不产生历史记录, 默认replace={false}
< Link to="/detail" replace={ true }>
学新通
  • <NavLink / > 组件和<Link / > 组件使用一致。是激活版的 <Link / >组件,可以实现导航的“高亮”效果。通常的使用场景是在同一个界面,tab栏切换,导航高亮,展示对应。
import { NavLink } from "react-router-dom";

// NavLink 组件的class 会返回含有isActive的对象,为true的时间,改导航路由被激活。
<NavLink to="/go" className={({ isActive }) => {
  return isActive ? "red" : "blue"
}}> go </NavLink>

4. <Navigate / >

  • <Navigate / > 组件被渲染,路径被修改,切换视图。
  • 可以定义replace属性,来控制跳转模式(模式是push, 会产生历史记录)
import { Navigate  } from "react-router-dom";

<Navigate to="/" />
<Navigate to="/" replace={true} />

5. <Outlet / >

  • 当route 发生嵌套的时候,必须使用<Outlet / >组件来渲染子路由对应的视图。 类似 props.children, 或者 vue-router中的 <router-veiw / >,子路由渲染组件占位符。
import { Routes, Route, Outlet } from "react-router-dom";

function Module() {
  return (
    <div>
      <h2>我是Modules组件</h2>
      // 如果不写 <Outlet /> 组件,<Item /> 视图是渲染不出来的。
      <Outlet />
    </div>
  )
}

function Item() {
  return (
    <div>
      <h2>我是Item组件</h2>
    </div>
  )
}

function App() {
  return (
    <Routes>
      <Route to="/tab" element={ <Module /> }>
        <Route to="item" element={ <Item /> }>
      </Route>
    </Routes>
  )
}
学新通
  1. <Route to=“” element={ } replace={ true } />
  2. < Link to=“” replace={true} / >
  3. <Navigate to=“/” replace={true} / >

组件定义replace 的三种方式。

三:router hooks

以下通过js调用,实现像组件形式的路由,获取参数,重定向等。

1. useRoutes()

  • 接收数组生成路由表,动态创建Routes 和 Route。 类似vue-router, 通过js配置路由;
// router.jsx
// 这里也可以定义纯js,定义router.js配置路由,类似vue中那样配置路由。
import React from "React"
import { useRoutes, Navigate } from "react-router-dom"
import Home from "../views/home.jsx";
import Loading from "./components/loading.jsx";
// 利用React.lazy 懒加载组件
const List = React.lazy(() => import("../views/list.jsx"))

// 懒加载组件
function lazyComponent(path) {
  const Comp = React.lazy(() => import(`../views/${path}`));
  return (
    // fallcack 可自定义全局<Loading />组件,在切换页面或模块显示loading过程,提高用户体验。
    <React.Suspense fallback={ <Loading title="加载中..." /> }>
      <Comp />
    </React.Suspense>
  )
}

const routes = [
  {
    path: "/",
    element: <Home />
  },
  {
    path: "/list",
    element: <List />
  },
  {
    path: "/detail",
    element: lazyComponent("detail.jsx")
  },
  {
    path: "/",
    element: <Navigate to="/login" />
  }
]

export const RouteList = () => {
  const router = useRoutes(routes);
  return <> { router } </>
}

// App.js
import { RouteList } from "./router.jsx"
function App(){
  return <RouteList />
}
学新通

2. useNavigate()

通过useNavigate()返回的参数navigate是一个函数

  • 第一个参数是路径
  • 第二个参数为option配置对象
import { useNavigate } from "react-router-dom"

export const Demo = () => {
  const navigate = useNavigate();
  const handle = () => {
    navigate("/login", {
      replace: true,
      state: {
        name: "error"
      }
    })
    // 上述是state传参,params 和 searchParmas 传参的话, 需要手动拼接
    // - params
    navigate(`/detail/${id}`);
    // - searchParmas
    navigate(`/detail?name=${name}&age=${age}`);
  }
  return (
    <div>
      // 类似history.go(-1)
      <button onClick={() => navigate(-1)}>后退</button>
      // 类似history.go(1)
      <button onClick={() => navigate(1)}>前进</button>
      
      <button onClick={handle}>按钮</button>
    </div>
  )
}
学新通

3. useParams()

  • 匹配路由的params参数
// App.js
import { Routes, Route } from "react-router-dom"

<Routes>
   <Route to="/list/:id" element={<Detail />} />
</Routes>

// 访问路由http://localhost:8080/list/1
// detail.jsx
import { useParams } from "react-router-dom"

export const Detail = () => {
  // 获取URL中携带过来的params参数
  const { id } = useParams(); // id = 1
  return <div>detail</div>
}

学新通

4. useSearchParams()

  • 读取和修改当前位置的 URL 中的查询字符串
  • 返回一个包含两个值的数组,内容分别为:当前的seaech参数、更新search的函数
// App.js
import { useSearchParams } from "react-router-dom"

<Routes>
   <Route to="/list?name=wei&age=18" element={<Detail />} />
</Routes>

// 访问路由http://localhost:8080/list/1
// detail.jsx
import { useSearchParams } from "react-router-dom"

export const Detail = () => {
  // 获取URL中携带过来的searchParams参数
  const [search,setSearch] = useSearchParams();
  const name = search.get("name"); // wei
  const age = search.get("age");  // 18
  
  // 点击,url变成http://localhost:3000/detail?name=zhang&age=19
  return <div onClick={() => setSearch("name=zhang&age=19")}>设置urlParams</div>
}
学新通

5. useLocation()

  • 获取当前 location 信息,对标5.x中的路由组件的location属性
  • 使用state进行传参,对useLocation返回的对象进行解构赋值即可,同时不需要占位
import { useLocation } from "react-router-dom"

export const Detail = () => {
  const location = useLocation();
  console.log(location) // 打印内容如下:
  /*
        {
      hash: "",
      key: "ahn9u7sh",
      pathname: "/list",
      search: "?name=wei&age=18",
      state: {a: 1, b: 2}
  */
}

6. useMatch()

  • 返回当前匹配的信息,需要传入匹配的路由(不传会报错)
import { Route, Link, useMatch } from "react-router-dom"

<Route to="/test1" element={<Home />}></Route>
// Home 
<Link to="/test1"></Link>

export default function Home() {
  // const match = useMatch();  // 报错
  // const match = useMatch(""); // 不会报错
  const match = useMatch("/test1")
  console.log(match);
  /*
  {
    // 对应params参数
    params: {}
    pathname: "/test1"
    pathnameBase: "/test1"
    // 如果配置的路由是:/detail/:id, 这里的pattern 展示的就是/detail/:id
    pattern:  
    caseSensitive: false
    end: true
    path: "/test1"
  }
  */
}
学新通

7. useInRouterContext()

  • 是否处于路由上下文环境 返回boolean
import { useInRouterContext } from "react-router-dom"

function App(){
  const Context = useInRouterContext();
  console.log(Context);  // true
  return <div>App</div>
}

function Demo(){
  const Context = useInRouterContext();
  console.log(Context);  // false
  return <div>Demo</div>
}

ReactDOM.render(
    // App组件被路由组件包裹,而Demo组件没有被包裹
    <div>
        <Demo />
        <BrowserRouter >
            <App />
        </BrowserRouter>
    </div>
, document.getElementById('root'))
学新通

8. useNavigationType()

  • 返回用户的导航类型,用户是怎么进入当前页面的,包含有:POP, PUSH, REPLACE
  1. 返回的三种类型都是大写。
  2. pop 是根据url直接在浏览器打开。
import { useNavigationType, Outlet } from "react-router-dom"

export default function Home(){
  const navigationType = useNavigationType();
  console.log(navigationType); // 返回值:POP, PUSH, REPLACE
  return <><Outlet /></>
}

9. useOutlet()

  • 在嵌套路由中使用,父组件使用<Outlet / >, 当子组件渲染的时候,会展示嵌套路由的对象。如果嵌套路由没有挂载,返回是null。
import { useOutlet, Link, Outlet, Routes, Route } from "react-router-dom"

function Home(){
  const outlet = useOutlet();
  //当访问:http://localhost:8080/
  console.log(outlet); // null
  
  // 当访问:http://locahost:8080/main
  console.dir(outlet);
  /*
    $$typeof: Symbol(react.element)
    key: null
    props: {value: undefined, children: {…}}
    ref: null
    type: {$$typeof: Symbol(react.provider), _context: {…}}
    _owner: FiberNode {tag: 0, key: null, stateNode: null, elementType: ƒ, type: ƒ, …}
    _store: {validated: false}
    _self: null
    _source: null
  */
  return (
    <>
      <h2>Home</h2>
      <Link to="/main">go</Link>
      <Outlet />
    </>
  );
}

function Main() {
  return <div>main</div>;
}

<Routes>
  <Route path="/" element={<Home />}>
    <Route path="/main" element={<Main />} />
  </Route>  
</Routes>
学新通

10. useResolvedPath()

  • 用来解析url值,返回一个对象,对象包含有hash,pathname,search 三个属性。
import { useResolvedPath } form "react-router-dom"

export default function Home() {
  // 注意:detail的 “/” 不要忘了,否则会拼接地址栏的url
  const pathObj = useResolvedPath("/detail?name=wei&age=18");
  console.log(pathObj);
  /*
  {
    hash: ""
    pathname: "/detail"
    search: "?name=wei&age=18"
  }
  */
}

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfheeb
系列文章
更多 icon
同类精品
更多 icon
继续加载