type
status
date
slug
summary
tags
category
icon
password
Router
详细使用示例
注意:这里使用的时最新的 v6 版本,已完全弃用了原先的 react-router 库,较 v5 版本有很大的改动。
一、基本使用
- 首先安装依赖
- 引入实现路由所需的组件,以及页面组件
path
:路径
element
:要渲染的组件
注意:BrowserRouter组件最好放在最顶层所有组件之外,这样能确保内部组件使用 Link 做路由跳转时不出错
二、路由跳转
在跳转路由时,如果路径是
/
开头的则是绝对路由,否则为相对路由,即相对于当前 URL进行改变2.1 Link 组件
Link组件
只能在Router
内部使用,因此使用到Link组件
的组件一定要放在顶层的 Router 之内2.2 NavLink 组件
NavLink组件
和Link组件
的功能是一致的,区别在于可以判断其to属性
是否是当前匹配到的路由
NavLink组件
的style
或className
可以接收一个函数,函数接收一个含有isActive
字段的对象为参数,可根据该参数调整样式
2.3 编程式跳转
使用
useNavigate
钩子函数生成navigate函数
,可以通过 JS 代码完成路由跳转useNavigate`取代了原先版本中的`useHistory
- 可以直接传入要跳转的目标路由(可以使用相对路径,语法和 JS 相同)
- 传入
1
表示后退
四、动态路由参数(URL参数)
4.1 路径参数
- 在
Route组件
中的path属性
中定义路径参数
- 在组件内通过
useParams
hook 访问路径参数
路径匹配规则
当URL同时匹配到含有路径参数的路径和无参数路径时,有限匹配没有参数的”具体的“(specific)路径。
如上的两个路径,将会匹配
teams/new
。路径的正则匹配已被移除。
兼容类组件
在以前版本中,组件的
props
会包含一个match对象
,在其中可以取到路径参数。但在最新的 6.x 版本中,无法从 props 获取参数。
并且,针对类组件的
withRouter
高阶组件已被移除。因此对于类组件来说,使用参数有两种兼容方法:- 将类组件改写为函数组件
- 自己写一个 HOC 来包裹类组件,用
useParams
获取参数后通过 props 传入原本的类组件
4.2 search 参数
- 查询参数不需要在路由中定义
- 使用
useSearchParams
hook 来访问和修改查询参数。其用法和useState
类似,会返回当前对象和更改它的方法
- 使用
setSearchParams
时,必须传入所有的查询参数,否则会覆盖已有参数
五、嵌套路由
5.1 路由定义
通过嵌套的书写
Route组件
实现对嵌套路由的定义。path 开头为 / 的为绝对路径,反之为相对路径。
5.2 在父组件中展示
在父组件中使用
Outlet
来显示匹配到的子组件5.3 在组件中定义
可以在任何组件中使用
Routes
组件,且组件内的Routes中,路径默认带上当前组件的路径作为前缀。注意:此时定义父组件的路由时,要在后面加上
/*
,否则父组件将无法渲染。六、默认路由
定义: 在嵌套路由中,如果 URL 仅匹配了父级 URL,则
Outlet
中会显示带有index
属性的子路由。可以使用在路由的任何层级- 当 url 为
/foo
时:Foo 中的 Outlet 会显示 Default 组件
- 当 url 为
/foo/bar
时:Foo 中的 Outlet 会显示为 Bar 组件
七、全匹配路由
定义:
path
属性取值为*
时,可以匹配任何(非空)路径,该匹配拥有最低的优先级。可以用于设置 404 页面。八、多组路由
通常,一个应用中只有一个
Routes
组件。但根据实际需要也可以定义多个路由出口(如:侧边栏和主页面都要随 URL 而变化)
九、路由重定向
当在某个路径
/a
下,要重定向到路径/b
时,可以通过Navigate
组件进行重定向到其他路径等价于以前版本中的Redirect组件
十、布局路由
当多个路由有共同的父级组件时,可以将父组件提取为一个没有
path
和 index
属性的Route组件(Layout Route)这种写法等价于:
十一、订阅和操作 history stack的原理
浏览器会记录导航堆栈,以实现浏览器中的前进后退功能。在传统的前端项目中,URL的改变意味着向服务器重新请求数据。
在现在的客户端路由( client side routing )中,可以做到编程控制URL改变后的反应。如在点击a标签的回调函数中使用
event.preventDefault()
阻止默认事件,此时URL的改变不会带来任何UI上的更新。11.1 History对象
浏览器没有直接提供监听URL改变(push、pop、replace)的接口,因此
react-router
对原生的 history
对线进行了包装,提供了监听URL改变的API。使用
react-router
时不需操作History对象(Routes
组件会进行操作)11.2 Location对象
react-router
对 window.location
进行包装后,提供了一个形式简洁的Location对象,形如:state
不显示在页面上,不会引起刷新,只由开发人员操作。
可用于记录用户的跳转详情(从哪跳到当前页面)或在跳转时携带信息。
可以用在
Link
组件或 navigate
方法中在目标的组件中,可以用
useLocation
方法获取该对象state中的信息会进行序列化,因此如日期对象等信息会变为string
key
每个Location对象拥有一个唯一的key,可以据此来实现基于Location的滚动管理,或是数据缓存。
如:将
location.key
和 URL 作为键,每次请求数据前,先查找缓存是否存在来判断是否实际发送请求,来实现客户端数据缓存。十二、 各类Router组件
12.1 HashRouter和BrowserRouter的区别
HashRouter
只会修改URL中的哈希值部分;而BrowserRouter
修改的是URL本身
HashRouter
是纯前端路由,可以通过输入URL直接访问;使用时BrowserRouter
直接输入URL会显示404,除非配置Nginx将请求指向对应的HTML文件。初次进入/
路径时或点击Link
组件跳转时不会发送请求
12.2 unstable_HistoryRouter
使用
unstable_HistoryRouter
需要传入一个 history
库的实例,这将允许在非react作用于下操作history对象。由于项目使用的history和react-router中使用的history版本可能不一样,该API目前标为unstable状态
12.3 MemoryRouter
HashRouter
和 BrowserRouter
都是依据外部对象(history)进行导航,而 MemoryRouter
则是自己存储和管理状态堆栈,多用于测试场景。12.4 NativeRouter
推荐的用于 React Native的Router组件
12.5 StaticRouter
在nodejs端使用,渲染react应用。
十三、使用JS对象定义路由(路由表)
使用
useRoutes
hook,可以使用一个JS对象而不是Routes组件与Route组件来定义路由。其功能类似于react-router-config(opens new window)useRoutes
的返回是 React Element,或是 null。此功能用来管理路由表,相比v5,可能需要借助一些第三方库来实现路由config管理,现在v6版本自带
(一) 创建路由表
对于传入的配置对象, 其类型定义如下:
提示
也可以单独创建 routes 文件夹管理路由表,然后在组件内使用 useRoutes
(二) 组件结构内使用函数返回值作为占位符
(三) 嵌套路由
在一级路由下面创建二级子路由
- 引入路由路由占位符OutLet到组件中
- 引入NavLink到组件中改变路径,子路由路径可以不需要加
/
注意
不要忘记使用Outlet作为占位符
(四) 路由懒加载
十四、其他hooks函数
直接在组件中调用即可
useRouterContext
作用:判断组件是否被路由包裹
useNavigationType
作用:判断路由跳转方式
返回值:
push
pop
replace
pop是在浏览器中直接打开了这个路由的组件
useOutlet
作用:查看组件下级路由信息
组件若未被挂载则返回null,若以被挂载,则返回该子组件信息
useResolvePath
作用:解析路径
动态路由
router/index.ts 默认路由
redux login/action.ts
注意带 //import! 的标识 每次导航列表更新时,再触发路由更新action handelFilterRouter 就是根据导航菜单列表 和权限列表 得出路由表的
utils 工具函数处理
说一说我这里为什么要映射element 成对应组件这部操作,原因是我使用了redux-persist(redux持久化。
若是直接转换后存入本地再取出来渲染是会有问题的,所以需要先将element保存成映射路径,然后渲染前再进行一次路径映射出对应组件。
每个后台的数据返回格式都不一样,需要自己去转换,我这里的转换仅供参考。 ps:defaulyRoutes和默认router/index.ts导出是一样的,可以做个小优化,复用起来。
App.tsx
路由传参
1. params传参
优点:刷新页面,参数不丢失
缺点:1.只能传字符串,传值过多url会变得很长 2. 参数必须在路由上配置
路由配置
路由跳转与获取路由参数
2. search传参
优点:刷新页面,参数不丢失
缺点:只能传字符串,传值过多url会变得很长,获取参数需要自定义hooks
路由配置
路由跳转与获取路由参数
3. state传参🙌
优点:可以传对象
缺点:
<HashRouter>
刷新页面,参数丢失路由配置
路由跳转与获取路由参数
笔记
<HashRouter>
不支持 location.key
与 location.state
,<HashRouter>
通过state
传递参数,刷新页面后参数丢失,官方建议使用<BrowserRouter>
,<BrowserRouter>
页面刷新参数也不会丢失。Router
详细使用示例
注意:这里使用的时最新的 v6 版本,已完全弃用了原先的 react-router 库,较 v5 版本有很大的改动。
一、基本使用
- 首先安装依赖
- 引入实现路由所需的组件,以及页面组件
path
:路径
element
:要渲染的组件
注意:BrowserRouter组件最好放在最顶层所有组件之外,这样能确保内部组件使用 Link 做路由跳转时不出错
二、路由跳转
在跳转路由时,如果路径是
/
开头的则是绝对路由,否则为相对路由,即相对于当前 URL进行改变2.1 Link 组件
Link组件
只能在Router
内部使用,因此使用到Link组件
的组件一定要放在顶层的 Router 之内2.2 NavLink 组件
NavLink组件
和Link组件
的功能是一致的,区别在于可以判断其to属性
是否是当前匹配到的路由
NavLink组件
的style
或className
可以接收一个函数,函数接收一个含有isActive
字段的对象为参数,可根据该参数调整样式
2.3 编程式跳转
使用
useNavigate
钩子函数生成navigate函数
,可以通过 JS 代码完成路由跳转useNavigate`取代了原先版本中的`useHistory
- 可以直接传入要跳转的目标路由(可以使用相对路径,语法和 JS 相同)
- 传入
1
表示后退
四、动态路由参数
4.1 路径参数
- 在
Route组件
中的path属性
中定义路径参数
- 在组件内通过
useParams
hook 访问路径参数
路径匹配规则
当URL同时匹配到含有路径参数的路径和无参数路径时,有限匹配没有参数的”具体的“(specific)路径。
如上的两个路径,将会匹配
teams/new
。路径的正则匹配已被移除。
兼容类组件
在以前版本中,组件的
props
会包含一个match对象
,在其中可以取到路径参数。但在最新的 6.x 版本中,无法从 props 获取参数。
并且,针对类组件的
withRouter
高阶组件已被移除。因此对于类组件来说,使用参数有两种兼容方法:- 将类组件改写为函数组件
- 自己写一个 HOC 来包裹类组件,用
useParams
获取参数后通过 props 传入原本的类组件
4.2 search 参数
- 查询参数不需要在路由中定义
- 使用
useSearchParams
hook 来访问和修改查询参数。其用法和useState
类似,会返回当前对象和更改它的方法
- 使用
setSearchParams
时,必须传入所有的查询参数,否则会覆盖已有参数
五、嵌套路由
5.1 路由定义
通过嵌套的书写
Route组件
实现对嵌套路由的定义。path 开头为 / 的为绝对路径,反之为相对路径。
5.2 在父组件中展示
在父组件中使用
Outlet
来显示匹配到的子组件5.3 在组件中定义
可以在任何组件中使用
Routes
组件,且组件内的Routes中,路径默认带上当前组件的路径作为前缀。注意:此时定义父组件的路由时,要在后面加上
/*
,否则父组件将无法渲染。六、默认路由
定义: 在嵌套路由中,如果 URL 仅匹配了父级 URL,则
Outlet
中会显示带有index
属性的子路由。可以使用在路由的任何层级- 当 url 为
/foo
时:Foo 中的 Outlet 会显示 Default 组件
- 当 url 为
/foo/bar
时:Foo 中的 Outlet 会显示为 Bar 组件
七、全匹配路由
定义:
path
属性取值为*
时,可以匹配任何(非空)路径,该匹配拥有最低的优先级。可以用于设置 404 页面。八、多组路由
通常,一个应用中只有一个
Routes
组件。但根据实际需要也可以定义多个路由出口(如:侧边栏和主页面都要随 URL 而变化)
九、路由重定向
当在某个路径
/a
下,要重定向到路径/b
时,可以通过Navigate
组件进行重定向到其他路径等价于以前版本中的Redirect组件
十、布局路由
当多个路由有共同的父级组件时,可以将父组件提取为一个没有
path
和 index
属性的Route组件(Layout Route)这种写法等价于:
十一、订阅和操作 history stack的原理
浏览器会记录导航堆栈,以实现浏览器中的前进后退功能。在传统的前端项目中,URL的改变意味着向服务器重新请求数据。
在现在的客户端路由( client side routing )中,可以做到编程控制URL改变后的反应。如在点击a标签的回调函数中使用
event.preventDefault()
阻止默认事件,此时URL的改变不会带来任何UI上的更新。11.1 History对象
浏览器没有直接提供监听URL改变(push、pop、replace)的接口,因此
react-router
对原生的 history
对线进行了包装,提供了监听URL改变的API。使用
react-router
时不需操作History对象(Routes
组件会进行操作)11.2 Location对象
react-router
对 window.location
进行包装后,提供了一个形式简洁的Location对象,形如:state
不显示在页面上,不会引起刷新,只由开发人员操作。
可用于记录用户的跳转详情(从哪跳到当前页面)或在跳转时携带信息。
可以用在
Link
组件或 navigate
方法中在目标的组件中,可以用
useLocation
方法获取该对象state中的信息会进行序列化,因此如日期对象等信息会变为string
key
每个Location对象拥有一个唯一的key,可以据此来实现基于Location的滚动管理,或是数据缓存。
如:将
location.key
和 URL 作为键,每次请求数据前,先查找缓存是否存在来判断是否实际发送请求,来实现客户端数据缓存。十二、 各类Router组件
12.1 HashRouter和BrowserRouter的区别
HashRouter
只会修改URL中的哈希值部分;而BrowserRouter
修改的是URL本身
HashRouter
是纯前端路由,可以通过输入URL直接访问;使用时BrowserRouter
直接输入URL会显示404,除非配置Nginx将请求指向对应的HTML文件。初次进入/
路径时或点击Link
组件跳转时不会发送请求
12.2 unstable_HistoryRouter
使用
unstable_HistoryRouter
需要传入一个 history
库的实例,这将允许在非react作用于下操作history对象。由于项目使用的history和react-router中使用的history版本可能不一样,该API目前标为unstable状态
12.3 MemoryRouter
HashRouter
和 BrowserRouter
都是依据外部对象(history)进行导航,而 MemoryRouter
则是自己存储和管理状态堆栈,多用于测试场景。12.4 NativeRouter
推荐的用于 React Native的Router组件
12.5 StaticRouter
在nodejs端使用,渲染react应用。
十三、使用JS对象定义路由(路由表)
使用
useRoutes
hook,可以使用一个JS对象而不是Routes组件与Route组件来定义路由。其功能类似于react-router-config(opens new window)useRoutes
的返回是 React Element,或是 null。此功能用来管理路由表,相比v5,可能需要借助一些第三方库来实现路由config管理,现在v6版本自带
(一) 创建路由表
对于传入的配置对象, 其类型定义如下:
提示
也可以单独创建 routes 文件夹管理路由表,然后在组件内使用 useRoutes
(二) 组件结构内使用函数返回值作为占位符
(三) 嵌套路由
在一级路由下面创建二级子路由
- 引入路由路由占位符OutLet到组件中
- 引入NavLink到组件中改变路径,子路由路径可以不需要加
/
注意
不要忘记使用Outlet作为占位符
(四) 路由懒加载
十四、其他hooks函数
直接在组件中调用即可
useRouterContext
作用:判断组件是否被路由包裹
useNavigationType
作用:判断路由跳转方式
返回值:
push
pop
replace
pop是在浏览器中直接打开了这个路由的组件
useOutlet
作用:查看组件下级路由信息
组件若未被挂载则返回null,若以被挂载,则返回该子组件信息
useResolvePath
作用:解析路径
动态路由
router/index.ts 默认路由
redux login/action.ts
注意带 //import! 的标识 每次导航列表更新时,再触发路由更新action handelFilterRouter 就是根据导航菜单列表 和权限列表 得出路由表的
utils 工具函数处理
说一说我这里为什么要映射element 成对应组件这部操作,原因是我使用了redux-persist(redux持久化。
若是直接转换后存入本地再取出来渲染是会有问题的,所以需要先将element保存成映射路径,然后渲染前再进行一次路径映射出对应组件。
每个后台的数据返回格式都不一样,需要自己去转换,我这里的转换仅供参考。 ps:defaulyRoutes和默认router/index.ts导出是一样的,可以做个小优化,复用起来。
App.tsx
路由传参
1. params传参
优点:刷新页面,参数不丢失
缺点:1.只能传字符串,传值过多url会变得很长 2. 参数必须在路由上配置
路由配置
路由跳转与获取路由参数
2. search传参
优点:刷新页面,参数不丢失
缺点:只能传字符串,传值过多url会变得很长,获取参数需要自定义hooks
路由配置
路由跳转与获取路由参数
3. state传参🙌
优点:可以传对象
缺点:
<HashRouter>
刷新页面,参数丢失路由配置
路由跳转与获取路由参数
笔记
<HashRouter>
不支持 location.key
与 location.state
,<HashRouter>
通过state
传递参数,刷新页面后参数丢失,官方建议使用<BrowserRouter>
,<BrowserRouter>
页面刷新参数也不会丢失。- 作者:慕雨
- 链接:https://www.axin.work/article/da005316-1867-4005-97f7-79a0df30cdf3
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。