1 jsx语法规则
定义虚拟dom时,不要写引号。
const vdom = <h1>lishan</h1>
标签中引入js表达式要用
{}
样式的类名指定不要用
class
,要用className
内联样式要用
style={{key: value}}
的形式,第一层括号表示引用js表达式,第二层括号表示是一个对象只有一个根标签
标签必须闭合
标签首字母
- 若小写字母开头,则将该标签转为html同名元素,若html无同名元素,则报错
- 若大写字母开头,react渲染对应的组件,若组件没定义,则报错
2 组件
2.1 函数式组件
1 | function MyComponent() { |
- React解析组件标签,找到了
MyCompoent
组件。 - 发现组件是函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,然后渲染到页面中。
2.2 类式组件
1 | class MyComponent extends React.Component { |
- React解析组件标签,找到了
MyCompoent
组件。 - 发现组件是类定义的,随后
new
出该类的实例,并通过该实例调用原型的render
方法。 - 将类中
render
返回的虚拟DOM转为真实DOM,然后渲染到页面中。
3 组件实例的三大核心属性
3.1 state
1 | class Weather extends React.Component { |
解决changeWeather
中this
指向问题
1 | class Weather extends React.Component { |
state
简化方式
1 | class Weather extends React.Component { |
3.2 props
在组件标签中写属性和值,会传入到对象中的props
中。
1 | class Weather extends React.Component { |
批量props
传入
1 | class Weather extends React.Component { |
props
的限制
1 | class Person extends React.Component { |
props
的简写
1 | class Person extends React.Component { |
函数式组件使用props
1 | function MyComponent(props) { |
3.3 refs
字符串形式的refs
(不推荐使用,大量使用会有较大的效率问题)
1 | class Demo extends React.Component { |
回调函数形式的refs
1 | class Demo extends React.Component { |
回调函数形式的refs
中的回调函数执行次数:
如果ref
回调函数以内联函数方式定义,在更新过程中会执行两次,第一次传入参数为null
,然后第二次传入参数DOM
元素。通过将ref
的回调函数定义成class
的绑定函数的方式避免上述问题。但这种影响不是很大,简单起见可以写成内联函数样式
1 | class Demo extends React.Component { |
createRef
的使用(当前React官方最推荐的方式)
1 | class Demo extends React.Component { |
❗不要过度使用refs
4 React事件处理
- 通过
onXxx
属性指定事件处理函数- React使用的是自定义(合成)事件,而不是原生的DOM事件
- React中的事件是通过委托方式处理的(委托给组件最外层的元素)
- 通过
event.target
得到发生事件的DOM元素对象(可以省略部分ref
的使用)
1 | class Demo extends React.Component { |
5 受控组件和非受控组件
5.1 非受控组件
数据“现用现取”
1 | class Demo extends React.Component { |
5.2 受控组件
例如,input
输入的数据,每次改变时将数据维护到state
中,当需要时直接从state
中获取
1 | class Demo extends React.Component { |
🎉
推荐使用受控组件,减少ref
的使用。
6 高阶函数和柯里化
6.1 高阶函数
如果需要实时保存很多输入的数据,并且保存的方式都相同,那么下面这种方式会很冗余麻烦。
1 | class Demo extends React.Component { |
可以采用给方法传参方式标识需要保存的数据是哪个类型(属性)
1 | class Demo extends React.Component { |
高阶函数的定义:
- 若函数接收的参数是一个函数,那该函数是高阶函数
- 若函数返回值是一个函数,该函数是高阶函数
6.2 柯里化
函数的柯里化:通过函数调用继续返回函数的形式,实现多次接收参数最后统一处理的函数编码形式。
1 | // 柯里化 |
不使用柯里化的方式:
1 | class Demo extends React.Component { |
7 生命周期
7.1 卸载组件
1 | ReactDOM.unmountComponentAtNode(document.getElementById("test")) |
7.2 组件将要挂载周期
1 | class Demo extends React.Component { |
7.3 组件完成挂载周期(常用)
1 | class Demo extends React.Component { |
7.4 组件将要卸载周期(常用)
1 | class Demo extends React.Component { |
7.5 是否应该组件更新周期
setState()
直接触发该周期
1 | class Demo extends React.Component { |
7.6 组件将要更新周期
forceUpdate()
直接触发该周期
1 | class Demo extends React.Component { |
7.7 组件完成更新周期
1 | class Demo extends React.Component { |
7.8 组件将要接收Props周期
1 | class Demo extends React.Component { |
7.9 新旧生命周期对比
新生命周期图:
7.10 从Props获得派生状态周期
这个钩子使用极其罕见
1 | class Demo extends React.Component { |
7.11 更新前获得快照周期
1 | class Demo extends React.Component { |
8 diffing算法
虚拟DOM中key的作用:
- 简单的说: key是虚拟DOM对象的标识, 在更新显示时key起着极其重要的作用。
- 详细的说:
当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】,
随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则如下:
- 旧虚拟DOM中找到了与新虚拟DOM相同的key:
- 若虚拟DOM中内容没变, 直接使用之前的真实DOM
- 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
- 旧虚拟DOM中未找到与新虚拟DOM相同的key根据数据创建新的真实DOM,随后渲染到到页面
- 旧虚拟DOM中找到了与新虚拟DOM相同的key:
用index作为key可能会引发的问题: 1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作: 会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。 2. 如果结构中还包含输入类的DOM: 会产生错误DOM更新 ==> 界面有问题。 3. 注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作, 仅用于渲染列表用于展示,使用index作为key是没有问题的。
开发中如何选择key?:
最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
如果确定只是简单的展示数据,用index也是可以的。
9 脚手架
9.1 创建项目并启动
- 全局安装
npm install -g create-react-app
- 在需要创建项目的目录下
create-react-app hello-react
- 进入
hello-react
目录 - 命令行执行
npm run start
启动项目即可看到默认页面
9.2 样式的模块化
样式文件名要以xxx.module.css
结尾
1 | .color { |
在jsx
组件里引入
1 | import hello from "./Hello.module.css" |
样式模块化主要是为了防止不同组件中样式名相同导致的样式覆盖问题。或者使用less
嵌套编写样式。
9.3 vscode插件
vscode
插件,提供一些代码片段,提高编码速度
9.4 组件化编码流程
- 拆分组件:拆分界面,抽取组件
- 实现静态组件:使用组件实现静态页面效果
- 实现动态组件:
- 动态显示初始化数据
- 数据类型
- 数据名称
- 保存在哪个组件
- 交互(从绑定事件监听开始)
- 动态显示初始化数据
10 消息订阅与发布pubsub
安装包
npm install pubsub-js
引入
import PubSub from "pubsub-js"
订阅消息
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
32import React, { Component } from "react"
import PubSub from "pubsub-js"
export default class Subscribe extends Component {
state = { info: "lishan" }
// 接收消息的方法参数为两个分别是消息名(主题名)和接受的实际数据
receiveInfo = (msg, info) => {
this.setState({ info })
}
// 组件挂载完成后订阅消息
componentDidMount() {
// 订阅哪个消息,以及用哪个方法处理该消息的数据,返回toekn表示该订阅的唯一标识符,方便后期取消订阅
this.token = PubSub.subscribe("test", this.receiveInfo)
}
/*
或者这么写,直接写在订阅里
componentDidMount() {
this.token = PubSub.subscribe("test", (msg, info) => {
this.setState({ info })
})
}
*/
// 组件将要卸载时取消订阅
componentWillUnmount() {
PubSub.unsubscribe(this.token)
}
render() {
return <div>{this.state.info}</div>
}
}发布消息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import PubSub from "pubsub-js"
import React, { Component } from "react"
export default class Publish extends Component {
sendInfo = () => {
// 发送消息,参数为消息名(主题名)和实际的数据
PubSub.publish("test", "test PubSub")
}
render() {
return (
<div>
<button onClick={this.sendInfo}>发送消息</button>
</div>
)
}
}
11 fetch(待更新)
12 React-Router 5
12.1 库安装
react-router
总共分为三个版本,分别给web
native
和任意端使用,这里只安装web
端,方便使用。
1 | npm install react-router-dom |
12.2 简单使用
❗当前版本为5版本,新版本会有不同
App.jsx
代码
1 | import React, { Component } from "react" |
Home
组件代码
1 | import React, { Component } from "react" |
About
组件代码
1 | import React, { Component } from "react"; |
12.3 路由组件和一般组件
写法不同:
一般组件:
<Demo />
路由组件:
<Route path="/demo " component={Demo } />
存放位置不同
一般组件:
components
路由组件:
pages
接收到的
props
不同路由组件会收到以下内容(只列举出常用的):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24history:
action: "PUSH"
block: ƒ block(prompt)
createHref: ƒ createHref(location)
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
length: 4
listen: ƒ listen(listener)
push: ƒ push(path, state)
replace: ƒ replace(path, state)
location:
hash: ""
key: "o2ti2g"
pathname: "/home"
search: ""
state: undefined
match:
isExact: true
params: {}
path: "/home"
url: "/home"
12.4 NavLink组件
NavLink
可以指定选中某个链接时使用哪个样式
<NavLink activeClassName="class-name" to="/home">home</NavLink>
封装NavLink
组件
如果多个NavLink
组件共用样式,会造成样式的代码冗余,对此进行封装为MyNavLink
组件,代码为:
1 | import React, { Component } from "react"; |
在其他组件使用时直接和NavLink
组件一样使用即可:
<MyNavLink to="/home" otherParams={1}>Home</MyNavLink>
❗组件使用props
传值时,除了可以自定义标签属性传值如:<Demo a={1} />
,这样会将a
传递到this.props.a
中。也可以将标签体中的内容传递到props
中,使用this.props.children
属性保存标签体的内容,标签体存储的key
这个是固定的名字无法修改。
自定义封装的MyNavLink
组件,在标签体中写入内容会被传到this.props.children
中,而children
会传递给NavLink
中的标签属性中的children
,达到<NavLink>test</NavLink>
的效果。
12.5 Switch组件
进行路由匹配时,会逐个比对匹配,如果有多个路径匹配则会展示多个组件页面,影响效率。此时在外层包裹Switch
组件,保证匹配上一个路由后停止匹配。(因为多数情况下一个路径匹配一个组件)
1 | <Switch> |
12.6 多级路由刷新页面央视丢失
public/index.html
中引入样式时不用./
用/
public/index.html
中引入样式时不用./
用%PUBLIC_URL%
(常用),%PUBLIC_URL%
脚手架提供的,表示绝对路径
12.7 路由模糊匹配与严格匹配
React默认开始模糊匹配
1 | <Link to="/home">home</Link><br /> |
如上所示的代码,默认模糊匹配时,链接设置的路径前缀包含路由的路径,则可以匹配上。
1 | <Route exact path="/about" component={About} /> |
如果开启严格匹配则不能匹配上。
❗默认情况下不做修改,只用模糊匹配即可。如果出现使用模糊匹配导致页面有问题,再开启严格匹配。
12.8 Redirect重定向
1 | <Route path="/home" component={Home} /> |
12.9 嵌套路由
一级路由
1 | <Switch> |
二级路由
1 | // 注册子路由要写上父路由的path值 |
点击/home
,路由匹配时,会按照注册顺序进行匹配,首先展示一级路由,路由按顺序匹配,匹配到了/home
路径展示Home
组件,该组件会有News Message
两个路由组件。当点击/home/news
时,根据路由的模糊匹配,首先会匹配到一级路由/home
,渲染该组件到页面中,会把子组件也渲染,就会注册二级路由,进而进行路由匹配,会匹配到/home/news
,展示News
组件。
此时如果开启严格模式,则会导致不能使用二级路由,因为一级路由没有匹配上,二级路由无法注册,也无法匹配。
12.10 路由传参
传递
params
参数1
2
3
4
5
6
7
8<MyNavLink to="/home/news">News</MyNavLink>
// 通过在链接最后拼接的方式将参数携带到链接里
<MyNavLink to={`/home/message/${infoId}`}>Message</MyNavLink>
<Switch>
<Route path="/home/news" component={News} />
{/* 接收参数时使用 :infoId 的形式占位,表示接收参数并指定参数的名字 */}
<Route path="/home/message/:infoId" component={Message} />
</Switch>接收到的参数在组件里的
this.props.match.params
对象里。传递
search
参数1
2
3
4
5
6
7
8<MyNavLink to="/home/news">News</MyNavLink>
// 通过?在链接最后拼接key=value&key=value的形式传参
<MyNavLink to={`/home/message?infoId=${infoId}`}>Message</MyNavLink>
<Switch>
<Route path="/home/news" component={News} />
{/* 注册路由无需改变 */}
<Route path="/home/message" component={Message} />
</Switch>接收到的参数保存在:
this.props.location.search
字符串里,是一个urlencoded
编码的字符串,需要手动转成字典对象,可以使用第三方库querystring
简称qs
。传递
state
参数1
2
3
4
5
6
7<MyNavLink to="/home/news">News</MyNavLink>
// 把to属性的值写成一个对象
<MyNavLink to={{pathname: "/home/message", state: {infoId: 1}}}>Message</MyNavLink>
<Switch>
<Route path="/home/news" component={News} />
<Route path="/home/message" component={Message} />
</Switch>接收到的参数保存在
this.props.location.state
对象中。此种方式传递的参数不会显示在地址栏中,隐私性较高。刷新也会保留住参数。如果清除缓存,则不会保留住。
12.11 push和replace
默认使用push
模式,切换路由会向历史栈中压栈,如果使用replace
则会替换当前页面,不会压栈。
12.12 编程式路由导航
编程式代替Link
组件。
1 | // 传递params |
12.13 withRouter
主要用于一般组件中使用路由组件特有的方法如:push replace
等。
1 | import {withRouter} from "react-router-dom" |
13 redux(待更新)
14 扩展
14.1 setState
setState更新状态的2种写法
1 | (1). setState(stateChange, [callback])------对象式的setState |
14.2 lazyLoad
路由组件的lazyLoad
1 | //1.通过React的lazy函数配合import()函数动态加载路由组件 ===> 路由组件代码会被分开打包 |
14.3 Hooks
- React Hook/Hooks是什么?
1 | (1). Hook是React 16.8.0版本增加的新特性/新语法 |
- 三个常用的Hook
1 | (1). State Hook: React.useState() |
- State Hook
1 | (1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作 |
- Effect Hook
1 | (1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子) |
- Ref Hook
1 | (1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据 |
14.4 Fragment
使用
<Fragment>
</Fragment>
或者写<></>
作用
可以不用必须有一个真实的DOM根标签了
14.5 Context
理解
一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信
使用
1 | 1) 创建Context容器对象: |
注意
在应用开发中一般不用context, 一般都用它的封装react插件
14.6 组件优化
Component的2个问题
只要执行setState(),即使不改变状态数据, 组件也会重新render()
只当前组件重新render(), 就会自动重新render子组件 ==> 效率低
效率高的做法
只有当组件的state或props数据发生改变时才重新render()
原因
Component中的shouldComponentUpdate()总是返回true
解决
办法1:
重写shouldComponentUpdate()方法
比较新旧state或props数据, 如果有变化才返回true, 如果没有返回false
办法2:
使用PureComponent
PureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true
注意:
只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false
不要直接修改state数据, 而是要产生新数据
项目中一般使用PureComponent来优化
14.7 render props
如何向组件内部动态传入带内容的结构(标签)?
Vue中:
使用slot技术, 也就是通过组件标签体传入结构 <AA><BB/></AA>
React中:
使用children props: 通过组件标签体传入结构
使用render props: 通过组件标签属性传入结构, 一般用render函数属性
children props
<A>
<B>xxxx</B>
</A>
{this.props.children}
问题: 如果B组件需要A组件内的数据, ==> 做不到
render props
<A render={(data) => <C data={data}></C>}></A>
A组件: {this.props.render(内部state数据)}
C组件: 读取A组件传入的数据显示 {this.props.data}
14.8 错误边界
理解:
错误边界:用来捕获后代组件错误,渲染出备用页面
特点:
只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误
使用方式:
getDerivedStateFromError配合componentDidCatch
1 | // 生命周期函数,一旦后台组件报错,就会触发 |
14.9 组件通信方式总结
方式:
props:
(1).children props
(2).render props
消息订阅-发布:
pubs-sub、event等等
集中式管理:
redux、dva等等
conText:
生产者-消费者模式
组件间的关系
父子组件:props
兄弟组件(非嵌套组件):消息订阅-发布、集中式管理
祖孙组件(跨级组件):消息订阅-发布、集中式管理、conText(用的少)
15 React-Router 6
15.1 概述
React Router 以三个不同的包发布到 npm 上,它们分别为:
- react-router: 路由的核心库,提供了很多的:组件、钩子。
- react-router-dom:</strong >
包含react-router所有内容,并添加一些专门用于
DOM 的组件,例如
<BrowserRouter>
等 。 - react-router-native:
包括react-router所有内容,并添加一些专门用于ReactNative的API,例如:
<NativeRouter>
等。
与React Router 5.x 版本相比,改变了什么?
内置组件的变化:移除
<Switch/>
,新增<Routes/>
等。语法的变化:
component={About}
变为element={<About/>}
等。新增多个hook:
useParams
、useNavigate
、useMatch
等。官方明确推荐函数式组件了!!!
......
15.2 Component
<BrowserRouter>
- 说明:
<BrowserRouter>
用于包裹整个应用。 - 示例代码:
1
2
3
4
5
6
7
8
9import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<BrowserRouter>
{/* 整体结构(通常为App组件) */}
</BrowserRouter>,root
);- 说明:
<HashRouter>
- 说明:作用与
<BrowserRouter>
一样,但<HashRouter>
修改的是地址栏的hash值。 - 备注:6.x版本中
<HashRouter>
、<BrowserRouter>
的用法与 5.x 相同。
- 说明:作用与
<Routes/> 与 <Route/>
- v6版本中移出了先前的
<Switch>
,引入了新的替代者:<Routes>
。 <Routes>
和<Route>
要配合使用,且必须要用<Routes>
包裹<Route>
。<Route>
相当于一个 if 语句,如果其路径与当前 URL 匹配,则呈现其对应的组件。<Route caseSensitive>
属性用于指定:匹配时是否区分大小写(默认为 false)。- 当URL发生变化时,
<Routes>
都会查看其所有子<Route>
元素以找到最佳匹配并呈现组件 。 <Route>
也可以嵌套使用,且可配合useRoutes()
配置 “路由表” ,但需要通过<Outlet>
组件来渲染其子路由。- 示例代码:
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>- v6版本中移出了先前的
<Link>
- 作用: 修改URL,且不发送网络请求(路由链接)。
- 注意:
外侧需要用
<BrowserRouter>
或<HashRouter>
包裹。 - 示例代码:
1
2
3
4
5
6
7
8
9import { Link } from "react-router-dom";
function Test() {
return (
<div>
<Link to="/路径">按钮</Link>
</div>
);
}<NavLink>
- 作用:
与
<Link>
组件类似,且可实现导航的“高亮”效果。 - 示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 注意: NavLink默认类名是active,下面是指定自定义的class
//自定义样式,如果NavLink过多,可以将箭头函数单独定义,减少代码量
<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>- 作用:
与
<Navigate>
可以把该组件理解为
Redirect
重定向- 作用:只要
<Navigate>
组件被渲染,就会修改路径,切换视图。 replace
属性用于控制跳转模式(push 或 replace,默认是push)。- 示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14import 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>
)
}- 作用:只要
<Outlet>
- 当
<Route>
产生嵌套时,渲染其对应的后续子路由。非嵌套时不用这个组件 - 示例代码:
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//根据路由表生成对应的路由规则
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>
{/* to可以直接写子路由的path,注意不要加/,如果加了则表示从头开始匹配,不加则是在当前路由下匹配 */}
<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>
)
}- 当
15.3 Hooks
useRoutes()
- 作用:根据路由表,动态创建
<Routes>
和<Route>
。 - 示例代码:
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>
)
}- 作用:根据路由表,动态创建
useNavigate()
- 作用:返回一个函数用来实现编程式导航。
- 示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import 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) // 后退
// navigate(1) // 前进
}
return (
<div>
<button onClick={handle}>按钮</button>
</div>
)
}useParams()
- 作用:返回当前匹配路由的
params
参数,类似于5.x中的match.params
。 - 示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import 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>
);
}- 作用:返回当前匹配路由的
useSearchParams()
- 作用:用于读取和修改当前位置的 URL 中的查询字符串。
- 返回一个包含两个值的数组,内容分别为:当前的seaech参数、更新search的函数。
- 示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import 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>
)
}useLocation()
- 作用:获取当前 location
信息,对标5.x中的路由组件的
location
属性。 - 示例代码:
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// 传递state参数
// <Link to="/home" state={{id: 1}} >主页</Link>
// 接收使用useLocation()获取location对象,该对象的state存储的是参数
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>
)
}- 作用:获取当前 location
信息,对标5.x中的路由组件的
useMatch()
- 作用:返回当前匹配信息,对标5.x中的路由组件的
match
属性。 - 示例代码:
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>
)
}- 作用:返回当前匹配信息,对标5.x中的路由组件的
useInRouterContext()
作用:如果组件在 <Router>
的上下文中呈现,则
useInRouterContext
钩子返回 true,否则返回 false。
useNavigationType()
- 作用:返回当前的导航类型(用户是如何来到当前页面的)。
- 返回值:
POP
、PUSH
、REPLACE
。 - 备注:
POP
是指在浏览器中直接打开了这个路由组件(刷新页面)。
useOutlet()
- 作用:用来呈现当前组件中渲染的嵌套路由。
- 示例代码:
1
2
3
4const result = useOutlet()
console.log(result)
// 如果嵌套路由没有挂载,则result为null
// 如果嵌套路由已经挂载,则展示嵌套的路由对象useResolvedPath()
作用:给定一个 URL值,解析其中的:path、search、hash值。