持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
前言
前面我们讲到在react-router-dom里,对于地址的匹配依托于path-to-regexp这个第三方库。
该库提供了多个方法,其中最主要的是pathToRegexp方法,而react-router里的match正是通过该方法去实现。
回顾
先看看router给切换组件注入的props有哪些,通过下列代码,我们进入http://localhost:3000/a页面,并查看控制台打印结果:
import React from 'react'
import {BrowserRouter as Router,Route} from 'react-router-dom'
export default function App() {
return (
<Router>
<Route path="/a" exact component={A} />
<Route path="/b" component={B} />
<Route path="/c" component={C} />
</Router>
)
}
function A(props){
console.log("props:",props)
return <h1>A</h1>
}
function B(){
return <h1>B</h1>
}
function C(){
return <h1>C</h1>
}
我们发现match对象里包含四个属性,可以通过被包裹的组件进行读取,分别是isExact(代表是否精确匹配)、params(代表地址匹配参数)、path(代表路径地址)、url(代表匹配到的路径)
实现
import { pathToRegexp } from "path-to-regexp"
/**
* @param {String} path 路径规则
* @param {String} pathname 页面路径地址的pathname
* @param {Object} options 相关配置,{sensitive,strict,isExct,}
*/
export default function pathMatch(path,pathname, options) {
const keys = []; //保存路径规则
const defaultOptions = {
sensitive: false, //是否区分大小写
strict: false, //是否为严格模式
exact: false, //是否匹配到字符串末尾
} //定义默认值
options = {
...defaultOptions,
...options
} //混合覆盖成新配置
const newOptions = {
sensitive: options.sensitive,
strict: options.strict,
end: options.exact,
} //配置
const regExp = pathToRegexp(path, keys, newOptions) //库的使用
const result = regExp.exec(pathname) //获取匹配结果
if (!result) {
return;
} //没有匹配到结果,直接返回
let resultArray = Array.from(result) //转换成真数组
const paramsArray = resultArray.slice(1) //去除数组第一项
let params = {}; //定义params对象
for (let i = 0; i < paramsArray.length; i++) {
params[keys[i]['name']] = paramsArray[i];
} //循环获得params对象
return {
isExact: pathname === result[0], //判断是否是精确匹配
params, //传入的路径规则
path, //匹配规则
url: result[0] //url地址上与params匹配到的部分
};
}
测试
在http://localhost:3000/blogId/123/a下运行下列代码:
import React from 'react'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import {pathToRegexp} from "path-to-regexp"
impport pathMatch from "./pathMatch.js"
export default function App() {
//测试代码:
const res1 = pathMatch("/blogId/:id", "/blogId/123/a", { exact: true, strict: true })
console.log("res1", res1)
const res2 = pathMatch("/blogId/:id", "/blogId/123/a", { exact: false, strict: true })
console.log("res2", res2)
const res3 = pathMatch("/blogId/:id", "/blogId/123/a", { exact: true, strict: false })
console.log("res3", res3)
const res4 = pathMatch("/blogId/:id", "/blogId/123/a", { exact: false, strict: false })
console.log("res4", res4)
return (
<Router>
<Route path="/a" exact component={A} />
<Route path="/b" component={B} />
<Route path="/c" component={C} />
</Router>
)
}
function A(props) {
return <h1>A</h1>
}
function B() {
return <h1>B</h1>
}
function C() {
return <h1>C</h1>
}
小结
在react-router内部,match的实现主要依托于path-to-regexp这个库,通过该库引入匹配规则和路径以及相关配置,即可获取包含路由信息的对象。