React路由,如何理解函数matchRoutes?对比useMatches
发布于 作者:苏南大叔 来源:程序如此灵动~在React Router
里面,测算当前路径匹配到了哪个路由,是个很重要的事情。因为可以通过自定义的路由数据获得很多额外的配置信息,本文内苏南大叔将要讲述的是matchRoutes()
函数,它的功用和useMatches()
这个钩子比较相似。但是,两者也有不同。可以根据实际的需求,来选择合适的钩子/函数。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。本文测试环境:nodejs@20.18.0
,create-react-app@5.0.1
,react-router-dom@6.27.0
,react@18.3.1
。matchRoutes()
和useMatches()
的功用类似,主要反馈了在全新的甚至毫不相关的路由条件下,可以匹配到那几条路由规则。
前文回顾
回顾一下相关的钩子函数:
useMatch()
,https://newsn.net/say/react-usematch.htmluseMatches()
,https://newsn.net/say/react-usematches.html
matchRoutes
本文讲述的函数叫做matchRoutes()
,值得注意的是:它没有以use
开头,这意味着它是个普通的函数,并不是一个钩子。并不是一个在react
世界里面遍地飞舞的钩子!!!
其官方文档:
matchRoutes runs the route matching algorithm for a set of routes against a given location to see which routes (if any) match. If it finds a match, an array of RouteMatch objects is returned, one for each route that matched.
大意就是:可以给出一个新的路由配置数据(原来的旧数组也可以),和一个新的location
对象(用当前的location
也可以),两者重新组合配对,最终返回一个新的匹配结果。
测试代码
如果使用旧的路由配置数组,使用当前location
的话,那么就是再次重新匹配了一次。和useMatches()
的效果差不多。当然,返回值也是有区别的。例子改编自上一篇文章:
routes.js
:
import React from "react";
import Post from "./Post";
import Detail from "./Detail";
const routers = [
{
path: "/detail/:id",
element: <Detail />,
tag: "独立详情页",
},
{
path: "/post/",
element: <Post />,
tag: "文章页",
children: [
{
path: ":id",
element: <Detail />,
tag: "嵌套详情页",
},
],
},
];
export default routers;
src/Post.js
:
import { useMatches,Outlet } from "react-router-dom";
export default () => {
const matches = useMatches();
console.log(matches);
return (
<div>
Post组件:useMatches()
<Outlet />
</div>
);
};
src/Detail.js
:
import { useMatches,useLocation,matchRoutes } from "react-router-dom";
import routes from "./routes";
export default () => {
const location = useLocation();
const matched = matchRoutes(routes, location);
console.log(matched);
return <div>Detail组件:matchRoutes(routes, location)</div>;
};
重大区别
这个matchRoutes()
返回值里面,带出了个.route
属性,它才是重要的角色。它可以完全反馈匹配的路由配置数组信息。也就是说配置在【路由数组里面的自定义属性,是可以取到的】!!!
访问同一个地址,/post/123
,对比输出。
const matches = useMatches();
console.log(matches);
输出:
[
{
"id": "1",
"pathname": "/post",
"params": {
"id": "123"
},
"data":undefined,
"handle":undefined,
},
{
"id": "1-0",
"pathname": "/post/123",
"params": {
"id": "123"
},
"data":undefined,
"handle":undefined,
}
]
const location = useLocation();
const matched = matchRoutes(routes, location);
console.log(matched);
输出:
[
{
"params": {
"id": "123"
},
"pathname": "/post",
"pathnameBase": "/post",
"route": {
"path": "/post/",
"element": {
"key": null,
"ref": null,
"props": {},
"_owner": null,
"_store": {}
},
"tag": "文章页",
"children": [
{
"path": ":id",
"element": {
"key": null,
"ref": null,
"props": {},
"_owner": null,
"_store": {}
},
"tag": "嵌套详情页"
}
]
}
},
{
"params": {
"id": "123"
},
"pathname": "/post/123",
"pathnameBase": "/post/123",
"route": {
"path": ":id",
"element": {
"key": null,
"ref": null,
"props": {},
"_owner": null,
"_store": {}
},
"tag": "嵌套详情页"
}
}
]
路由方式
在useMatches()
这个钩子里面,只能使用createXxxRouter()
+RouterProvider
的方式。但是这个限制,在matchRoutes()
里面是完全不存在的。
理论上来说,matchRoutes()
和当前的路由信息是完全没有关系的。它所使用的匹配规则是它的第一个参数。所以,两种路由写法,其实都和matchRoutes()
完全没有关系。所以,也可以这么说,支持两种路由写法了。
扩展代码
如果像 useMatches()
一样,取最最最符合当前地址的那条路由信息的话。可以这样获得:
function match(routes, location){
const matched = matchRoutes(routes, location);
const n = matched.length;
if (n > 0) return matched[n - 1].route;
else return null;
}
表格对比
useMatches() | matchRoutes() |
---|---|
没有参数 | 传参全新匹配 |
可获得.handle 里面的自定义属性 | 可直接获得自定义属性 |
结语
useMatches()
,还是和当前的路由匹配规则严格匹配的,其匹配的结果也是严格安装模版走的。如果把条件放松,规则和地址,都可以推倒重来的话,使用的就是matchRoutes()
了。其路由匹配结果比较自由,可以显示自定义的属性。
更多苏南大叔的react
经典文章,可以参考:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。