React@16.x(44)路由v5.x(9)源码(1)- path-to-regexp

admin2024-07-04  15

目录

  • 1,作用
  • 2,实现获取 match 对象
    • 2.1,match 对象的内容
    • 2.2,注意点
    • 2.3,实现

1,作用

之前在介绍 2.3 match 对象 时,提到了 react-router 使用第3方库 path-to-regexp 来匹配路径正则。

我们也利用它(版本v6.2.2),来手动实现一个获取类似 match 对象的方法。

2,实现获取 match 对象

2.1,match 对象的内容

  • 不匹配时,返回 null
  • 匹配时,返回一个对象

比如对下面的路由组件来说,

<Route path="/news/:id" component={News}></Route>

当访问 http://localhost:5173/news/123 时,返回的对象:

{
    "path": "/news/:id",
    "url": "/news/123",
    "isExact": true,
    "params": {
        "id": "123"
    }
}

2.2,注意点

先做个测试,看下返回内容。

import { pathToRegexp } from "path-to-regexp";

const path = "/news/:id";
const keys = [];
const regExp = pathToRegexp(path, keys);
console.log(regExp);
const result = regExp.exec(location.pathname);
console.log(result);
console.log(keys);

regExp 一个正则对象,

/^\/news(?:\/([^\/#\?]+?))[\/#\?]?$/i

result 匹配的结果,

[
    "/news/123",
    "123"
]

keys 的结果,

[
    {
        "name": "id",
        "prefix": "/",
        "suffix": "",
        "pattern": "[^\/#\?]+?",
        "modifier": ""
    }
]

除了 match.isExact 属性,其他的东西都有了。而 match.isExact 可通过 location.pathname === result[0] 判断。

另外,还需要注意一点,<Route> 组件可以设置 exact 来表示是否精确匹配。比如,

<Route path="/news/:id" exact></Route>

此时访问 http://localhost:5173/news/123/xxx 是并不匹配,matchnull

path-to-regexp 的默认配置项,是匹配到路径字符串结尾。所以这个配置项就相当于 exact

React@16.x(44)路由v5.x(9)源码(1)- path-to-regexp,在这里插入图片描述,第1张

2.3,实现

import { pathToRegexp } from "path-to-regexp";

/**
 * 返回一个类似 match 的对象。
 * @param {*} path 路径规则
 * @param {*} pathname 真实的地址
 * @param {*} options react-router-dom 的 Route 组件的配置项。
 */
export default function matchPath(path, pathname, options) {
    const keys = [];
    const regExp = pathToRegexp(path, keys, getOptions(options));
    const result = regExp.exec(pathname);
    if (!result) {
        return null;
    }
    const params = getParams(result.slice(1), keys);
    return {
        path,
        url: result[0],
        isExact: pathname === result[0],
        params,
    };
}

/**
 * 返回符合 path-to-regexp 的配置项属性。
 * @param {*} options
 * @returns
 */
function getOptions(options = {}) {
    const defaultOptions = {
        exact: false, // 不精确匹配
        sensitive: false, // 大小写敏感
        strict: false, // 严格模式
    };
    const opts = {
        ...defaultOptions,
        ...options,
    };
    return {
        end: opts.exact, // 更改 key
        sensitive: opts.sensitive,
        strict: opts.strict,
    };
}

function getParams(result, keys) {
    const obj = {};
    keys.forEach((f, index) => {
        obj[f.name] = result[index];
    });
    return obj;
}

测试1,

const match = pathMatch("/news/:id/:no", location.pathname);

当访问 http://localhost:5173/news/123/asd 时返回,

{
    "path": "/news/:id/:no",
    "url": "/news/123/asd",
    "isExact": true,
    "params": {
        "id": "123",
        "no": "asd"
    }
}

测试2,

const match = pathMatch("/news/:id/:no", location.pathname);

当访问 http://localhost:5173/news/123/asd/xxx 时返回,

{
    "path": "/news/:id/:no",
    "url": "/news/123/asd",
    "isExact": false,
    "params": {
        "id": "123",
        "no": "asd"
    }
}

以上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!