React Router6学习(包括组件和Hooks)


目录
  • React Router6学习
    • 1. 概述
      • 1.1 React Router以三个不同的包发布到npm上,他们分别是
      • 1.2 与React Router 5.x 版本相比,改变了什么?
    • 2. Component
      • 2.1 BrowserRouter
      • 2.2 HashRouter
      • 2.3
      • 2.4
      • 2.5
      • 2.6
      • 2.7
    • 3. 上课笔记
      • 1. 一级路由
      • 2. 重定向
      • 3. NavLink高亮
      • 4. useRoutes重定向
      • 5. 嵌套路由
        • outlet
        • to
        • end
      • 6. 路由的params参数以及useMatch钩子
        • useMatch
      • 7. 路由的search参数以及useLocation钩子
        • useLocation
      • 8. 路由的state参数
      • 9. 编程式路由导航
      • 10. useInRouterContext Hook的使用
      • 11. useNavigationType() Hook的使用
      • 12. useOutlet()
      • 13. useResolvedPath()

React Router6学习

第1节和第2节是课程中的MD笔记, 第3节是在听课过程中自己记的笔记和从网上查的总结, 细节更多.

1. 概述

1.1 React Router以三个不同的包发布到npm上,他们分别是

  1. react-router:路由的核心库, 提供了很多的:组件、钩子。
  2. react-router-dom:包含react-router所有内容,并添加了一些专门用于DOM的组件,例如等。
  3. react-router-native: 包括react-router所有内容,并添加一些专门用于ReactNative的API,例如:等。

1.2 与React Router 5.x 版本相比,改变了什么?

  1. 内置组件的变化:移除了,新增了等。
  2. 语法的变化: component={About} 变为了element={About}等。
  3. 新增多个hook:useParams useNavigate useMatch等。
  4. 官方明确推荐函数式组件了。

2. Component

2.1 BrowserRouter

  1. 说明:用于包裹整个应用。
  2. 示例代码:index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from "react-router-dom"
import App from './App';

ReactDOM.render(
  
      
  
  ,document.getElementById('root')
);

2.2 HashRouter

  1. 说明:作用和 一样, 但是修改的是地址的hash值。
  2. 备注:6.x版本中 的用法与5.x相同。

2.3

  1. V6版本中移除了先前的Switch,引入了全新的替代者Routes

  2. RoutesRoute要搭配使用,并且必须要用Routes包裹Route

  3. Route相当于一个if语句,如果路径与当前URL匹配,则呈现其对应的组件。

  4. 属性用于指定:匹配时是否区分大小写(默认为false)。

  5. 当URL发生变化时,都会查看其所有子 元素以找到最佳匹配并呈现组件。

  6. 也可以嵌套使用,且可以配合useRoutes()配置“路由表”,但需要通过组件来渲染其子路由。

  7. 示例代码:


    } />
    } />
    }/>

  1. 作用: 修改URL, 且不发送网络请求(路由链接).

  2. 注意: 外侧需要用包裹

  3. 示例代码:

    import {Link} from 'react-router-dom'
    
    function Test() {
    	return (
    		
    按钮
    ) }
  1. 作用: 与 组件类似, 且可实现导航的"高亮"效果.

2.6

  1. 作用:只要组件被渲染,就会修改路径,切换视图。
  2. replace属性用于控制跳转模式 (push 或 replace,默认是push)

2.7

  1. 产生嵌套时,渲染其对应的后续子路由。
  2. 在后续路子由组件的想要展示的位置上使用, 即可渲染。

3. 上课笔记

1. 一级路由

首先需要安装react路由包: npm i react-router-dom

  1. 使用路由:在App.jsx中从react-router-dom中引入BrowserRouter来包裹App组件

  2. 创建路由链接:可以使用react-router-dom中的linkNavLink来创建路由链接,其中NavLink可具有高亮效果。

以前我们的应用如果需要在各个页面之间切换,使用锚点元素实现的话,在每次点击时,页面会被重新加载,React Router提供了 和 来避免这种情况的发生。当你点击时,url会更新,组件会被重新渲染,但是页面不会重新加载。

组件最终会被渲染成HTML标签的url的时候给已经渲染的元素添加参数,组件的属性有:

  • activeClassName(string):设置选中样式,默认值为active
  • 需要将className写成一个函数:
  • activeStyle(object):当元素被选中时,为此元素添加样式
  • exact(bool):为true时,只有当导致和完全匹配class和style才会应用
  • strict(bool):为true时,在确定为位置是否与当前URL匹配时,将考虑位置pathname后的斜线
  • isActive(func)判断链接是否激活的额外逻辑的功能
    ————————————————
    版权声明:本文为CSDN博主「冰雪为融」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/lhjuejiang/article/details/80366839
  1. 注册路由:使用的组件由SWitch(已删除)改为Routes,还要需要使用RouteRoute是用来被包裹的,一个来包裹多个, 语法为:

router path 代表的是路由链接地址,React Component代表的是如果匹配成功所使用的组件名字。

}>

2. 重定向

当我们什么路由链接都没输入,就相当于是'/'时,就会出现警告,No routes matched location "/", 这个时候我们就需要使用重定向来解决问题。

使用的组件由Redirect改为Navigate,语法为, 其中about为匹配不到路径时所跳转到的组件:

} />

Navigate组件只要渲染就会引起视图的切换,可以用此特性来控制当页面达到某一条件时,启用Navigate组件来进行视图切换,举一个小例子

import React, {useState} from 'react'
import { Navigate } from 'react-router-dom'

export default function Home() {
  const [count,setCount] = useState(0)

  return (
    

我是Home的内容

{ count === 2 ? :

当前count值是{count}

}
) }

其实Navigate组件中还有一个属性,replace, 可以控制跳转的模式,默认为false, 即push模式。

} />

3. NavLink高亮

NavLink路由链接在点击的时候,会给他加一个class属性,值默认是active,在使用bootstrap的时候就会出现高亮效果。

首先我们要知道在我们点击一个连接的时候,会传入一个对象,里面有isActive属性,值为true。

利用这个特性我们可以写一个函数来计算样式,然后在className中使用这个函数,关键代码如下:

function computedClassName({isActive}) {
    return isActive? 'list-group-item atguigu': 'list-group-item'
}

{/* 路由链接 */} About Home

4. useRoutes重定向

之前我们是这样注册路由的:


    } />
    } />
    }/>

其实可以发现中间除了path值和element值不一样以外,基本都是相同的结构,所以我们就可以使用useRoutes来注册路由。

在我们有路由的项目中,一般会有两个特殊的文件夹,一个是pages,里面存放的是各个路由的组件。另外一个是routes,里面存放的是路由表,里面的index.js一般是如下类似代码:

import About from '../pages/About'
import Home from '../pages/Home'
import { Navigate } from 'react-router-dom'

// 创建路由表,可以用来注册路由
const routerList =  [
    {
        path:'/about',
        element:
    },
    {
        path:'/home',
        element:
    },
    {
        path:'/',
        element:
    },
]

export default routerList;

然后我们只需要在需要使用注册路由的组件里使用useRoutesHooks来实现了:

import {NavLink,useRoutes} from "react-router-dom"

export default function App() {
  // 根据路由表生成对应的路由
  const element = useRoutes(routerList)
  
  ......
  {/* 路由链接 */}
  About
  Home
  {/* 注册路由 */}
  {element}
  ......
}

这样做的好处是可以把整个应用所有的路由都可以在routes文件夹下进行统一的管理,而且能够让代码可读性更好,也契合了未来Hooks发展的方向。

5. 嵌套路由

outlet

Outlet像是一个槽位,如果匹配上了就在Outlet组件所在的地方进行组件的展示,也就是说Outlet可以指定组件呈现的位置。

to

to属性内可以直接写最终地址,比如之前是/home/news, 现在可以直接写news,注意不要写成/news, 否则就成了从一级路由news里找,即从根路径下开始找。

routes/index.js

import About from '../pages/About'
import Home from '../pages/Home'
import { Navigate } from 'react-router-dom'
import Message from '../pages/Message'
import News from '../pages/News'


// 创建路由表,可以用来注册路由
const routerList =  [
    {
        path:'/about',
        element:
    },
    {
        path:'/home',
        element:,
        children:[
            {
                path:'news',
                element:
            },
            {
                path:'message',
                element:
            }
        ]
    },
    {
        path:'/',
        element:
    }
]

export default routerList;

Home.jsx关键代码:

import React from 'react'
import { NavLink, Outlet } from 'react-router-dom'

export default function Home() {

	return (
        

我是Home的内容

  • News
  • Message
{/* 指定路由组件呈现的位置 */}
) }

一共有三种路由路径的书写方式,以二级路由home组件下的news为例:

  • to='/home/news'
  • to='news'
  • to='./news'

end

还有一个值得一提的事是,目前我们页面所呈现的高亮的地方不仅有news, 而且还有一级路由home也是高亮的,我们如果不想让他高亮,那么就可以在该组件上加一个属性end,来代表当匹配的是该路由的子路由时,该路由不高亮。

Home

6. 路由的params参数以及useMatch钩子

一共有三种方式可以在路由进行传参操作:1. params参数 2. search 3. location.state

我们首先讲第一种,使用params参数:

// 1.Link路由链接的书写方式
{message.title}
// 2.路由表匹配规则
{
    path:'detail/:id/:title/:content',
    element:
}

// 接收使用
import { useParams } from "react-router-dom"

export default function Detail() {
    // 接收得到的参数是一个对象,我们可以使用结构的方式来获得他
    const { id, title, content } = useParams()
    return (
        
  • 消息编号:{id}
  • 消息标题:{title}
  • 消息内容:{content}
) }

useMatch

我们还可以使用useMatch钩子来获得之前match里面的参数,比如patten里的path参数等,具体使用语法如下,我们需要在所需要使用match参数的组件里把当前路径包括params写好:

import {useMatch} from "react-router-dom"
......
	const match = useMatch('/home/message/detail/:id/:title/:content')
    console.log(match)

7. 路由的search参数以及useLocation钩子

一共有三种方式可以在路由进行传参操作:1. params参数 2. search 3. location.state

我们来介绍第二种, 使用serach:

// 1. search传参的书写方式
messages.map(message => {
                        return (
                            // 路由链接
                            
  • {/* search传参 */} {message.title}
  • ) }) // 2.routes路由表不用改变任何东西 // 3.在接收参数的组件里,要使用useSearchParams hook来接收参数 import React from 'react' import { useSearchParams } from 'react-router-dom' export default function Detail() { // 类似于useState的使用方式,所存放的数据在search.get('...')里 const [search, setSearch] = useSearchParams() return (
    • 消息编号:{search.get('id')}
    • 消息标题:{search.get('title')}
    • 消息内容:{search.get('content')}
    ) }

    useLocation

    另外我们还可以使用useLocation钩子来获得loaction的数据,里面包括了pathname和经过转化后的search,具体的语法是:

    import { useLocation } from 'react-router-dom'
    ......
    	const location = useLocation()
        console.log(location);
    

    8. 路由的state参数

    一共有三种方式可以在路由进行传参操作:1. params参数 2. search 3. location.state

    我们来介绍第三种, 使用location.state,当然就是使用的上面提到过的useLocation钩子:

    // 1. 路由链接
        
  • {/* state传参 */} {message.title}
  • // 2. routes路由表不需要做任何的改动,同search一样 // 3. 在接收参数的组件里,要使用useLocation hook来接收参数 import React from 'react' import { useLocation } from 'react-router-dom' export default function Detail() { const location = useLocation() const { id, title, content } = location.state return (
    • 消息编号:{id}
    • 消息标题:{title}
    • 消息内容:{content}
    ) }

    9. 编程式路由导航

    之前我们都是借助this.props.history来对对象上的API对操作路由跳转\前进和后退, 可是在函数式组件中我们并不能使用this, 这个时候我们借助useNavigate这个Hook来实现.

    首先我们来对其中的replace和state传参来进行说明:

    // 引入useNavigate钩子
    import { Link, Outlet,useNavigate } from 'react-router-dom'
    
    // 使用钩子,得到的navigate是一个函数
    const navigate = useNavigate()
    const showDetail = (message) => {
        const {id, title, content} = message
        navigate('detail',{
            // 指定是否为替换的方式
            replace:false,
            // 传递state参数
            state:{
                id,
                title,
                content
            }
        })
    }
    
    // 在组件上使用函数来使用该navigate函数
    
    

    但是我们知道在之前的react router5里面非路由组件是不能使用this.props.history的, 但是在react router6里面, 我们只需要使用useNavigate这个钩子, 就可以实现非路由组件使用编程式路由导航, 并且可以实现页面的回退和前进, 具体实现如下所示, components文件夹(此文件夹存放非路由组件)下的Header组件源代码如下所示:

    import React from 'react'
    import { useNavigate } from 'react-router-dom'
    
    export default function Header() {
        const navigate = useNavigate()
        
        const backward = () => {
            navigate(-1)
        }
    
        const forward = () => {
            navigate(1)
        }
        return (
            

    React Router6 Demo

    ) }

    10. useInRouterContext Hook的使用

    作用: 如果组件在的上下文中呈现, 则useInRouterContext钩子返回为 true, 否则返回 false.

    比如说我们的App组件是被包裹的, App组件及其所有的子组件都是处于路由的上下文环境中的, 不区分是否是路由组件.

    11. useNavigationType() Hook的使用

    1. 作用:返回当前的导航类型(用户是如何来到当前页面的)
    2. 返回值: POP PUSH REPLACE
    3. 备注: POP是指在浏览器中直接打开了这个路由组件(刷新页面)

    12. useOutlet()

    1. 作用, 用来呈现当前组件中要渲染的嵌套路由
    2. 示例代码:
    const result = useOutlet()
    console.log(result)
    // 如果嵌套路由没有挂载,则result为null
    // 如果嵌套路由已经挂载,则展示嵌套的路由对象
    

    13. useResolvedPath()

    1. 作用: 给定一个url值, 解析其中的: path search 和 hash值.