path-to-regexp

在vue-router/react-router/koa-router等路由工具中,定义路由格式形如:/user/:name 或者其他更复杂的路由匹配。其实现均依赖path-to-regexp.js,本章将和读者一起深入探究path-to-regexp实现原理,同时加强对正则表达式的理解

path-to-regex项目地址https://github.com/pillarjs/path-to-regexp

使用方法

const pathToRegexp = require('path-to-regexp')

// pathToRegexp(path, keys?, options?)
// pathToRegexp.parse(path)
// pathToRegexp.compile(path)
  • path 字符串/字符串数组/正则表达式

  • keys path路径中捕获到的匹配项等

  • options 配置项

    • sensitive 如果为 true 正则表达式大小写敏感 (默认: false)

    • strict 如果为true 正则表达式允许可选的尾随分隔符匹配 (default: false)

    • end 如果为 true 正则表达式将从字符串的结尾匹配 (default: true)

    • start 如果为 true 正则表达式将从字符串的开头匹配 (default: true)

    • delimiter 默认分割符号 (default: '/')

    • endsWith Optional character, or list of characters, to treat as "end" characters

    • whitelist 解析时要考虑分隔符的字符列表 (default: undefined, any character)

暴露函数

使用module.exports对模块外暴露下述方法

全局变量

全局变量中定义了路由默认分割符,以及路由匹配模式

从上述正则可视化图中可知,该正则匹配可拆分为3种子正则表达式,分别是:“(\\\\.)”“(?:\\:(\\w+)(?:\\(((?:\\\\.|)+)\\))?)([+*?])?”“(?:\\(((?:\\\\.|)+)\\))([+*?])?”;以下分别举例讲解:

  • 匹配转义模式

匹配字符串中包含转义\字符的路径,如:"/user/\\?"

  • 匹配命名路由参数,即:包含:key关键字模式

该匹配模式中,有2种子类型匹配模式,分别是:key,以及限制key模式的正则;可匹配路径,如:“/user/:id”,“/user/:id?”,“/user/:id(\\d{8})”,“/user/:id(\\d{8})?”,其中:key(),括号中的为正则表达式字符串

  • 匹配无命名路由参数,即:不包含:key关键字模式

该模式可匹配模式,如:/user/([\d]{8}),/user/([\d]{8})?

公共函数

path-to-regexp中包含2个对字符串进行编码的函数:escapeString,escapeGroup

  • escapeString,对正则中所有特殊字符进行编码

  • escapeGroup,对路由参数中自定义正则表达式进行编码

规定,在路由参数自定义正则表达式中不能存在=!:$/()等正则字符,固把这些字符进行转义

核心方法讲解

首先通过一个例子,了解pathToRegexp的输入和输出,如下输入“/user/:id(\d{8})?”时,输出“/^\/user(?:\/(\d{8}))?(?:\/)?$/i”

pathToRegexp 处理流程

从下图可知,path解析为tokens(parse)与tokens转换为正则(tokensToRegExp)为核心逻辑,接下来的章节将围绕这两个函数进行讲解

parse

该函数把path路径解析为tokens数组,其中tokens结构为:

从上述结构可知,tokens由n个token组成,其中每个token中的元素由路由执行正则PATH_REGEXP匹配并捕获而得到,那么匹配捕获项怎么和token对应起来呢?见示列:

见如下源码:

tokensToRegExp

该函数,把tokens数组转为路由正则表达式,继5.2. 中得到tokens,转换为正则表达式如下:

见下述,通过分析源码,了解tokens转为正则的实现细节

Last updated

Was this helpful?