0%

提供者与消费者模式

用于组孙组件通讯的场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import { useState, createContext, useContext } from 'react'
// createContext使用方式
const context = createContext() //createContext可以提供默认值,只有在没有 Provider时生效
const
// 祖先组件提供数据 关键字: Provider
function parent() {
return(
<context.Provider
value={{
color,
setColor,
}}
>
...
</context.Provider>
)
}


// 后代组件消费
// 1.使用 Consumer
function Child() {
return(
<context.Consumer>
{/*以函数传参形式消费*/}
{ value => ... }
</context.Consumer>
)
}

// 2. 使用 useContext
function Child() {
const value = useContext(context)
return() {
{value.xxx}...
}
}

Ref

React 支持一个特殊的、可以附加到任何组件上的 ref 属性。此属性可以是一个由 React.createRef() 函数创建的对象、或者一个回调函数、或者一个字符串(遗留 API)。当 ref 属性是一个回调函数时,此函数会(根据元素的类型)接收底层 DOM 元素或 class 实例作为其参数。这能够让你直接访问 DOM 元素或组件实例。

谨慎使用 ref。如果你发现自己经常使用 ref 来在应用中“实现想要的功能”,你可以考虑去了解一下自上而下的数据流(状态提升)。

useRef hook的作用:

1.配合ref属性,获取DOM对象,进行DOM操作
2.在组件更新期间维持一个值(也就是:可以在每次组件重新渲染时,拿到同一个值)

useRef hook 创建的ref对象,有以下特点:

1.ref对象有一个current属性,可以使用该属性存储任意值
2.修改ref对象current属性的值不会导致组件重新渲染

类式组件使用Ref

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// React.createRef
export default class MyComponent extends React.Component {
inputRef = React.createRef()
componentDidMount() {
this.inputRef.current.focus(); //直接访问DOM元素的属性
}
render() {
return <input type="text" ref={this.inputRef} />;
}


}

// 回调
export default class App extends React.Component {
componentDidMount() {
this.inputRef.focus()
}
render() {
return (
<input type="text" ref={(currentNode) => (this.inputRef = currentNode)} /> //往实例对象自身挂载
)
}
}

函数式组件使用Ref

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内持续存在。
import { useEffect, useRef } from 'react'
const App = () => {
const inputRef = useRef(null)
useEffect(() => {
inputRef.current.focus()
}, [])
return (
<div>
<input type="text" ref={inputRef} />
</div>
)
}
export default App

img图片下方出现缝隙

img是一种类似text的标签元素,在结束的时候,会在末尾加上一个空白符(匿名文本),导致下方会多出来3px间距
方法一:

1
2
3
img {
vertical-align: middle;
}

方法二:

1
2
3
4
img {
display: block;
}
// img设置为块级元素,text-align:center就不再生效,图片的水平居中应使用margin:auto

position:fixed遮挡问题

fixed是相对于浏览器窗口的固定定位,它的位置与文档流无关,因此不占据文档流空间
很多时候,开启了fixed的组件的z-index层级都很高,如固定在底部的TabBar,此时会出现遮挡底部组件的问题。给被遮挡的组件增加padding值就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{/* 路由链接,Link和NavLink最终会被转为<a>标签 to被转为href*/}
<NavLink to="login">登录</NavLink>
<NavLink to="register">注册</NavLink>
<NavLink to="home">主页</NavLink>
<NavLink to="mine">我的</NavLink>

{/* 注册路由,展示对应的路由组件,"/" 可省略 */}
<Routes>
<Route path="/Login" element={<Login />}></Route>
<Route path="/Register" element={<Register />}></Route>
<Route path="/Home/*" element={<Home />}></Route> {/* 有二级路由用 "/*"模糊匹配 */}
<Route path="/Mine" element={<Mine />}></Route>
<Route path="/" element={<Navigate to="/home" />}></Route> {/* 作用:只要<Navigate>组件被渲染,就会修改路径,切换视图 */}
</Routes>

使用路由表集中管理注册路由

react-router-dom version6支持原生路由表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// 创建routes目录,一般在src目录下创建
{/* 在routes.js下导入所有路由组件 */}
import { Navigate } from 'react-router-dom'
import Home from '../pages/Home'
import Login from '../pages/Login'
import Register from '../pages/Register'
import Mine from '../pages/Mine'
// 子路由
import Detail from '../pages/Home/Detail'
// 路由表,[{path:'...',element:</>,children:[{...}]},{...}]
export const routes = [
{
path:'/Home/*',
element: <Home />,
children:[
{
path:'Detail',
element: <Detail />
},
]
},
{
path:'/Login',
element: <Login />
},
{
path:'/Register',
element: <Register />
},
{
path:'/Mine',
element: <Mine />
},
{
path:'/',
element: <Navigate to="/Home" />
},
]

// 在对应路由文件中引入钩子函数 useRoutes、引入路由表文件
import { useRoutes } from 'react-router-dom'
import {routes} from './routes'
const App = () => {
const element = useRoutes(routes)
return(
<NavLink to="login">登录</NavLink>
<NavLink to="register">注册</NavLink>
<NavLink to="home">主页</NavLink>
<NavLink to="mine">我的</NavLink>
{/* before */}
<Routes>
<Route path="/Login" element={<Login />}></Route>
<Route path="/Register" element={<Register />}></Route>
<Route path="/Home/*" element={<Home />}></Route> {/* 有二级路由用 "/*"模糊匹配 */}
<Route path="/Mine" element={<Mine />}></Route>
<Route path="/" element={<Navigate to="/home" />}></Route>
</Routes>
{/* after */}
{element} // 等同于<Routes><Route></Route></Routes>
)
}
// 如示例代码中在路由组件<Home/>中有二级路由<Detail/>,那么在<Home/>组件中引入 Outlet
// home.js
import React from 'react'
import { NavLink,Outlet } from 'react-router-dom'
const Home = () => {
return (
<>
<div>主页</div>
<br />
<NavLink to="detail">详情</NavLink>
<Outlet /> // 和 {element} 相似
</>
)
}
export default Home

编程式路由导航

使用Link或NavLink方式跳转路由有很多的局限性,如在3秒后路由自动跳转,鼠标滑过图片路由跳转,这些用Link很难实现路由跳转。于是就有了编程式路由导航,不使用Link或NavLink就是编程式路由导航。

函数式

RouterV6版本使用useNavigate()进行编程式路由导航,useNavigate的作用就是返回一个函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 引入 useNavigate
import {useNavigate} from 'react-router-dom'
const App = () => {
const element = useRoutes(routes) // 路由表
const navigate = useNavigate() // 返回一个函数
const handle = () => {
// 第一种方式,指定具体的路径
navigate('/login',{ // 调用函数,参数1--->要跳转的路由路径
replace:false, // 参数2[可选]--->replace,路由跳转模式,默认push模式,有痕迹,replace模式,true时无痕迹
state:{a:1,b:2} // 向路由组件传递state参数,示例中就向<login/>传递了参数
})
// 第二种方式,传入数值进行前进或后退,类似于5.x中的history.go()方法
// navigate(-1)
}
return (
<div>
<button onClick={handle}>按钮</button>
</div>
)
}

RouterV5.1.0以上版本使用useHistory进行编程式路由导航

1
2
3
4
5
6
7
8
9
10
11
12
13
import { useHistory } from 'react-router-dom'
export default function App() {
const history = useHistory()

return(
...
<xxx
onClick={(e) => {
history.push(e.key)
}}
/>
)
}

类式

借助this.props.history中的属性也能实现路由跳转

使用 Effect Hook

Effect Hook 可以让你在函数组件中执行副作用操作,什么是副作用:有时候,我们只想在 React 更新 DOM 之后运行一些额外的代码。比如发送网络请求,手动变更 DOM,记录日志,这些都是常见的无需清除的副作用。还有一些副作用是需要清除的。例如订阅外部数据源。这种情况下,清除工作是非常重要的,可以防止引起内存泄露!

class中的钩子函数

1
2
3
4
5
6
7
componentDidMount()
// componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。
componentDidUpdate()
// componentDidUpdate() 会在更新后会被立即调用。首次渲染不会执行此方法。
componentWillUnmount()
// componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。
// componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

使用方式1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { useEffect, useState } from 'react'
const Count = () => {
const [count, setCount] = useState(0)
const addCount = () => {
setCount((pre) => pre + 1)
}
// 写法1
useEffect(() => {
console.log('useEffect钩子函数执行')
})
// 相当于调用componentDidMount() + componentDidUpdate()
return (
<div>
<div>{count}</div>
<button onClick={addCount}>+1</button>
</div>
)
}

使用方式2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { useEffect, useState } from 'react'
const Count = () => {
const [count, setCount] = useState(0)
const addCount = () => {
setCount((pre) => pre + 1)
}
// 写法2
useEffect(() => {
console.log('useEffect钩子函数执行')
},[])
// 相当于调用componentDidMount()
return (
<div>
<div>{count}</div>
<button onClick={addCount}>+1</button>
</div>
)
}
export default Count

使用方式3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { useEffect, useState } from 'react'
const Count = () => {
const [count, setCount] = useState(0)
const addCount = () => {
setCount((pre) => pre + 1)
}
// 写法3
useEffect(() => {
console.log('useEffect钩子函数执行')
},[count])
// 相当于调用componentDidMount() + componentDidUpdate(),
// 注意componentDidUpdate()被调用是有条件的,只有数组中的 count 更新时才会更新
return (
<div>
<div>{count}</div>
<button onClick={addCount}>+1</button>
</div>
)
}
export default Count

使用方式4

1
2
3
4
5
6
7
8
9
10
11
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline)
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange)
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange)
}
})
// 相当于调用componentDidMount() + componentWillUnmount(),

useEffect应用-发送请求

在组件中,可以使用useEffect Hook来发送请求(side effect)获取数据
注意:effect只能时一个同步函数,不能使用async
因为如果effect时async的,此时返回值时Promise对象。这样的话,就无法保证函数被立即调用
为了使用async/awair语法,可以在effect内部创建async函数,并调用
核心代码:

1
2
3
4
5
6
7
8
9
10
11
// 错误演示:不要给effect添加async
useEffect(async() => {
const res = await axios.get('http://xxx')
},[])
// 正确使用
useEffect(() => {
const loadData = async () => {
const res = await axios.get('http://xxx')
}
loadData()
},[])

pubsub-js

pubsub-js使用消息订阅发布机制用于组件之间传递数据,
理解订阅发布机制

订阅发布

1
2
3
4
5
6
// 导入包
npm i pubsub-js
or
yarn add pubsub-js

import PubSub from 'pubsub-js'
1
2
3
4
5
6
7
8
9
10
11
// A组件发布
// PubSub.publish('约定的主题', 要传的数据);
PubSub.publish('MY TOPIC', data)

// B组件订阅
// token跟setTimeout赋值同理,在销毁时使用,msg为'MY TOPIC',用_代替。data是接收到的数据
const token = PubSub.subscribe('MY TOPIC', (msg,data) => {...})

// 销毁订阅
PubSub.unsubscribe(token);

State的注意事项

函数组件中state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// setState方法更新状态是同步的,但是表现为延迟更新状态(注意:非异步更新状态)
// 调用setState时,将所有更新状态对象放在一个react的更新任务队列中暂存起来(没有立即更新),
// 如果多次调用 setState更新状态,状态会进行合并,后面覆盖前面
// 等到所有的操作都执行完毕,React会拿到最终的状态,然后触发组件更新
//优势:多次调用setState(),只会触发一次重新渲染,提升性能
state = {
count: 0,
}
addCount = () => {
this.setState({
count: this.state.count + 1,
})
this.setState({
count: this.state.count + 2,
})
this.setState({
count: this.state.count + 3,
})
console.log('count:',this.state.count) // count:0,只执行了一次
}

render() {
console.log('render') //render,只执行一次
return (
<>
<div>{this.state.count}</div> //3
<br />
<button onClick={this.addCount}>按钮</button>
</>
)
}
// 如果后面的状态需要依赖前一项状态的值,可以使用箭头函数的形式
// React内部会拿到第一次回调函数的结果,然后把这个最新的状态结果作为参数,传递给下次调用的回调函数
//这样,下一次调用就可以拿到上一次调用的结果(也是上一次更新后的状态值)
this.setState((previousState) => {
return { count: previousState.count + 1 }
})

什么是类

类是对象的模板,定义了对象的属性和方法

创建一个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 最基本的类
class MyClass {

}
// 创建一个示例对象的类
class MyClass {
constructor(...argu) { //实参会被构造函数 constructor 接收
console.log(argu); //['孙悟空',18]
}
}
const a = new MyClass('孙悟空',18)

//通过实例对象属性调用
class MyClass {
constructor(name,age) {
this.name = name
this.age = age
}
fn() {
console.log('打妖怪');
}
}
const a = new MyClass('孙悟空',18)
console.log(a.name,a.age); //孙悟空 18
a.fn() //打妖怪

类的this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyClass{
fn() {
console.log(this);
}
}
const a = new MyClass
a.fn() //this--->MyClass {},通过实例对象属性调用函数,this指向实例对象a

const b = a.fn // 将实例对象a的函数赋值给b
b() //this--->undefined,理论上this应该指向函数的调用者--->window,但在类区域中,默认开启严格模式,所以输出undefined
// 结论:通过实例对象调用函数,this指向该实例对象,通过普通函数调用,this指向undefined

//很多时候我们不希望this的指向变化,最简单的方式是使用箭头函数
class MyClass{
fn = () => console.log(this)
}
const a = new MyClass
a.fn() //MyClass {fn: ƒ}
const b = a.fn
b() //MyClass {fn: ƒ}

类的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Parent{
constructor(name,age) {
this.name = name
this.age = age
}
fn = () => {
console.log('我是父类,子类可以继承我的属性和方法');
}
}
//extends--->继承
class Chi1 extends Parent{

}
// 子类可以完全继承父类的属性和方法
const chi1 = new Chi1('我是子类1',18)
console.log(chi1.name,chi1.age); //我是子类1 18
chi1.fn() // 我是父类,子类可以继承我的属性和方法

// 子类可以重写父类的属性和方法
class Chi2 extends Parent{
constructor(name,age,sex) {
// 继承父类的构造函数
super(name,age)
// 自己的属性
this.sex = sex
}
fn = () => {
console.log('我是子类,我重写了父类中的方法')
}
}
const chi2 = new Chi2('我是子类2',19,'男')
console.log(chi2.name,chi2.age,chi2.sex) // 我是子类2 19 男
chi2.fn() //我是子类,我重写了父类中的方法

类的静态属性和方法

1
2
3
4
5
6
7
8
9
// 直接通过类调用的属性和方法被称为静态属性和静态方法(类属性,类方法)
class MyClass{
static name = '我是MyClass'
static fn = () => {
console.log('我是通过类直接调用的');
}
}
console.log(MyClass.name); //我是MyClass
MyClass.fn() //我是通过类直接调用的

React Router 6 快速上手

转自尚硅谷React教程

1.概述

  1. React Router 以三个不同的包发布到 npm 上,它们分别为:

    1. react-router: 路由的核心库,提供了很多的:组件、钩子。
    2. react-router-dom: 包含react-router所有内容,并添加一些专门用于 DOM 的组件,例如 <BrowserRouter>
    3. react-router-native: 包括react-router所有内容,并添加一些专门用于ReactNative的API,例如:<NativeRouter>等。
  2. 与React Router 5.x 版本相比,改变了什么?

    1. 内置组件的变化:移除<Switch/> ,新增 <Routes/>等。

    2. 语法的变化:component={About} 变为 element={<About/>}等。

    3. 新增多个hook:useParamsuseNavigateuseMatch等。

    4. 官方明确推荐函数式组件了!!!

      ……

2.Component

1. <BrowserRouter>

  1. 说明:<BrowserRouter> 用于包裹整个应用。

  2. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import React from "react";
    import ReactDOM from "react-dom";
    import { BrowserRouter } from "react-router-dom";

    ReactDOM.render(
    <BrowserRouter>
    {/* 整体结构(通常为App组件) */}
    </BrowserRouter>,root
    );

2. <HashRouter>

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

3. <Routes/> 与 <Route/>

  1. v6版本中移出了先前的<Switch>,引入了新的替代者:<Routes>

  2. <Routes><Route>要配合使用,且必须要用<Routes>包裹<Route>

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

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

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

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

  7. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <Routes>
    /*path属性用于定义路径,element属性用于定义当前路径所对应的组件*/
    <Route path="/login" element={<Login />}></Route>

    /*用于定义嵌套路由,home是一级路由,对应的路径/home*/
    <Route path="home" element={<Home />}>
    /*test1 和 test2 是二级路由,对应的路径是/home/test1 或 /home/test2*/
    <Route path="test1" element={<Test/>}></Route>
    <Route path="test2" element={<Test2/>}></Route>
    </Route>

    //Route也可以不写element属性, 这时就是用于展示嵌套的路由 .所对应的路径是/users/xxx
    <Route path="users">
    <Route path="xxx" element={<Demo />} />
    </Route>
    </Routes>
  1. 作用: 修改URL,且不发送网络请求(路由链接)。

  2. 注意: 外侧需要用<BrowserRouter><HashRouter>包裹。

  3. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import { Link } from "react-router-dom";

    function Test() {
    return (
    <div>
    <Link to="/路径">按钮</Link>
    </div>
    );
    }
  1. 作用: 与<Link>组件类似,且可实现导航的“高亮”效果。

  2. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 注意: NavLink默认类名是active,下面是指定自定义的class

    //自定义样式
    <NavLink
    to="login"
    className={({ isActive }) => {
    console.log('home', isActive)
    return isActive ? 'base one' : 'base'
    }}
    >login</NavLink>

    /*
    默认情况下,当Home的子组件匹配成功,Home的导航也会高亮,
    当NavLink上添加了end属性后,若Home的子组件匹配成功,则Home的导航没有高亮效果。
    */
    <NavLink to="home" end >home</NavLink>

6. <Navigate>

  1. 作用:只要<Navigate>组件被渲染,就会修改路径,切换视图。

  2. replace属性用于控制跳转模式(push 或 replace,默认是push)。

  3. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import React,{useState} from 'react'
    import {Navigate} from 'react-router-dom'

    export default function Home() {
    const [sum,setSum] = useState(1)
    return (
    <div>
    <h3>我是Home的内容</h3>
    {/* 根据sum的值决定是否切换视图 */}
    {sum === 1 ? <h4>sum的值为{sum}</h4> : <Navigate to="/about" replace={true}/>}
    <button onClick={()=>setSum(2)}>点我将sum变为2</button>
    </div>
    )
    }
    1
    2
    // 网页重定向
    <Route path='/' element={<Navigate to='/about'/>}/>

7. <Outlet>

  1. <Route>产生嵌套时,渲染其对应的后续子路由。

  2. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    //根据路由表生成对应的路由规则
    const element = useRoutes([
    {
    path:'/about',
    element:<About/>
    },
    {
    path:'/home',
    element:<Home/>,
    children:[
    {
    path:'news',
    element:<News/>
    },
    {
    path:'message',
    element:<Message/>,
    }
    ]
    }
    ])

    //Home.js
    import React from 'react'
    import {NavLink,Outlet} from 'react-router-dom'

    export default function Home() {
    return (
    <div>
    <h2>Home组件内容</h2>
    <div>
    <ul className="nav nav-tabs">
    <li>
    <NavLink className="list-group-item" to="news">News</NavLink>
    </li>
    <li>
    <NavLink className="list-group-item" to="message">Message</NavLink>
    </li>
    </ul>
    {/* 指定路由组件呈现的位置 */}
    <Outlet />
    </div>
    </div>
    )
    }

8. useRoutes

ReactRouter6支持路由表形式来统一管理路由,只能在函数式组件中使用useRoutes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { useRoutes } from 'react-router-dom'	// useRoutes
import {routes} from './routes'
export default function App() {
const element = useRoutes(routes)
......
{/* 注册路由 */}
{element}
}
// 路由表文件
通常在src目录下创建routes文件夹专门处理路由
import {Navigate} from 'react-router-dom' // 重定向
import About from '../pages/About' //需要引入的路由文件
import Home from '../pages/Home' //需要引入的路由文件
export const routes = [
{
path:'/about',
element:<About/>
},
{
path:'/home',
element:<Home/>
},
{
path:'/',
element:<Navigate to='/about'/>
},
]

3.Hooks

1. useRoutes()

  1. 作用:根据路由表,动态创建<Routes><Route>

  2. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    //路由表配置:src/routes/index.js
    import About from '../pages/About'
    import Home from '../pages/Home'
    import {Navigate} from 'react-router-dom'

    export default [
    {
    path:'/about',
    element:<About/>
    },
    {
    path:'/home',
    element:<Home/>
    },
    {
    path:'/',
    element:<Navigate to="/about"/>
    }
    ]

    //App.jsx
    import React from 'react'
    import {NavLink,useRoutes} from 'react-router-dom'
    import routes from './routes'

    export default function App() {
    //根据路由表生成对应的路由规则
    const element = useRoutes(routes)
    return (
    <div>
    ......
    {/* 注册路由 */}
    {element}
    ......
    </div>
    )
    }

2. useNavigate()

  1. 作用:返回一个函数用来实现编程式导航。

  2. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import React from 'react'
    import {useNavigate} from 'react-router-dom'

    export default function Demo() {
    const navigate = useNavigate()
    const handle = () => {
    //第一种使用方式:指定具体的路径
    navigate('/login', {
    replace: false,
    state: {a:1, b:2}
    })
    //第二种使用方式:传入数值进行前进或后退,类似于5.x中的 history.go()方法
    navigate(-1)
    }

    return (
    <div>
    <button onClick={handle}>按钮</button>
    </div>
    )
    }

3. useParams()

  1. 作用:回当前匹配路由的params参数,类似于5.x中的match.params

  2. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import React from 'react';
    import { Routes, Route, useParams } from 'react-router-dom';
    import User from './pages/User.jsx'

    function ProfilePage() {
    // 获取URL中携带过来的params参数
    let { id } = useParams();
    }

    function App() {
    return (
    <Routes>
    <Route path="users/:id" element={<User />}/>
    </Routes>
    );
    }

4. useSearchParams()

  1. 作用:用于读取和修改当前位置的 URL 中的查询字符串。

  2. 返回一个包含两个值的数组,内容分别为:当前的seaech参数、更新search的函数。

  3. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import React from 'react'
    import {useSearchParams} from 'react-router-dom'

    export default function Detail() {
    const [search,setSearch] = useSearchParams()
    const id = search.get('id')
    const title = search.get('title')
    const content = search.get('content')
    return (
    <ul>
    <li>
    <button onClick={()=>setSearch('id=008&title=哈哈&content=嘻嘻')}>点我更新一下收到的search参数</button>
    </li>
    <li>消息编号:{id}</li>
    <li>消息标题:{title}</li>
    <li>消息内容:{content}</li>
    </ul>
    )
    }

5. useLocation()

  1. 作用:获取当前 location 信息,对标5.x中的路由组件的location属性。

  2. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    import React from 'react'
    import {useLocation} from 'react-router-dom'

    export default function Detail() {
    const x = useLocation()
    console.log('@',x)
    // x就是location对象:
    /*
    {
    hash: "",
    key: "ah9nv6sz",
    pathname: "/login",
    search: "?name=zs&age=18",
    state: {a: 1, b: 2}
    }
    */
    return (
    <ul>
    <li>消息编号:{id}</li>
    <li>消息标题:{title}</li>
    <li>消息内容:{content}</li>
    </ul>
    )
    }




6. useMatch()

  1. 作用:返回当前匹配信息,对标5.x中的路由组件的match属性。

  2. 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <Route path="/login/:page/:pageSize" element={<Login />}/>
    <NavLink to="/login/1/10">登录</NavLink>

    export default function Login() {
    const match = useMatch('/login/:x/:y')
    console.log(match) //输出match对象
    //match对象内容如下:
    /*
    {
    params: {x: '1', y: '10'}
    pathname: "/LoGin/1/10"
    pathnameBase: "/LoGin/1/10"
    pattern: {
    path: '/login/:x/:y',
    caseSensitive: false,
    end: false
    }
    }
    */
    return (
    <div>
    <h1>Login</h1>
    </div>
    )
    }

7. useInRouterContext()

​ 作用:如果组件在 <Router> 的上下文中呈现,则 useInRouterContext 钩子返回 true,否则返回 false。

8. useNavigationType()

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

9. useOutlet()

  1. 作用:用来呈现当前组件中渲染的嵌套路由。

  2. 示例代码:

    1
    2
    3
    4
    const result = useOutlet()
    console.log(result)
    // 如果嵌套路由没有挂载,则result为null
    // 如果嵌套路由已经挂载,则展示嵌套的路由对象

10.useResolvedPath()

  1. 作用:给定一个 URL值,解析其中的:path、search、hash值。

github常用搜索条件

in:name xxx 名称条件
in:name xxx xxx 多个名称条件
stars:>xxx 点赞大于xxx的条件
in:readme xxx 搜索readme里的内容
fork:>xxx 按照项目fork数量,大于xxx的
size:>=xxx 项目大小,单位是kb
pushed:>2021-01-01 按照最后更新时间
language:xxx 项目使用语言
user:xxx 按作者名称搜索
in:description xxx 按照项目描述 description 搜索