Skip to content

2. 核心概念:路径模式、参数与修饰符

在上一章中,我们了解了 path-to-regexp 的核心流程。现在,是时候深入学习它的“语言”了。path-to-regexp 的强大之处在于它定义了一套简洁而富有表现力的语法,让我们能够精确地描述各种复杂的 URL 模式。本章将详细讲解这套语法的每一个细节,它是你掌握 path-to-regexp 的基石。

2.1. 路径的基本构成

一个路径模式通常由两种基本部分组成:

  • 静态片段 (Static Segments): 路径中的普通字符串部分,如 /users//posts。在转换时,它们会被转义并按原样成为正则表达式的一部分,用于进行精确的字面量匹配。
  • 动态片段 (Dynamic Segments): 路径中用于捕获动态值的“占位符”,我们称之为“参数”。它们是 path-to-regexp 语法的核心。

2.2. 命名参数 (Named Parameters)

最常见的参数形式是命名参数,它以冒号 : 作为前缀。

  • 语法: :name
  • 示例: /user/:id

这个模式会匹配像 /user/123/user/abc 这样的路径。path-to-regexp 会生成一个捕获组来获取 :id 位置的实际值,并将其与参数名 id 关联起来。

默认情况下,一个命名参数会匹配一个或多个非斜杠 (/) 的字符。其生成的正则表达式片段大致如下:

javascript
// Path: /user/:id
// RegExp fragment for :id: ([^\/]+?)
// Full RegExp: /^\/user\/([^\/]+?)\/?$/i

2.3. 修饰符 (Modifiers)

在参数后面添加修饰符,可以改变参数的匹配行为,使其成为可选的或可重复的。

修饰符语法示例含义生成正则片段 (示例)
?/:id?可选参数 (Optional)(?:\/([^\/]+?))?
*/:id*零或多个 (Zero or more)(?:\/([^\/]+?))*
+/:id+一或多个 (One or more)(?:\/([^\/]+?))+

让我们来仔细分析这些修饰符:

  • ? (可选): 它表示前面的参数是可选的。注意,生成的正则 (?:\/([^\/]+?))? 中,不仅参数的捕获组是可选的,连它前面的斜杠 / 也被包含在一个非捕获组 (?:...) 中并设为可选。这意味着 /user/:id? 既能匹配 /user/123,也能匹配 /user

  • * (零或多个): 它表示参数可以出现零次或多次。例如,/files/:path* 可以匹配 /files/files/a/files/a/b 等。每次匹配到的值都会被收集到一个数组中。

  • + (一或多个): 与 * 类似,但它要求参数至少出现一次。例如,/tags/:tag+ 可以匹配 /tags/js/tags/js/react,但不能匹配 /tags

2.4. 自定义参数匹配 (Custom Matching Parameters)

默认情况下,参数匹配的是 [^/]+?。但有时我们需要更精确的控制,比如,我们希望 :id 只能是数字。这时,可以在参数名后用括号 () 提供一个自定义的正则表达式片段。

  • 语法: :name(pattern)
  • 示例: /user/:id(\d+)

在这个例子中,我们为 :id 参数指定了 \d+ 的匹配模式,它表示“一个或多个数字”。

  • 生成正则: /^\/user\/(\d+)\/?$/i

现在,这个模式只能匹配像 /user/123 这样的路径,而无法匹配 /user/abc

自定义模式也可以和修饰符组合使用,创造出强大的匹配规则。一个经典的例子是贪婪匹配:

  • 示例: /files/:path(.*)
  • 解释: 这里的 .* 会匹配任意字符(包括斜杠 /)零或多次。这使得 :path 参数可以捕获一个包含多层目录的完整路径,例如在 /files/a/b/c.txt 中,:path 会匹配到 a/b/c.txt

2.5. 未命名参数 (Unnamed Parameters)

你也可以使用没有名称的参数,直接在路径中嵌入括号来提供一个正则表达式。

  • 语法: (.*)(\d+)
  • 示例: /post/(\d{4}-\d{2}-\d{2})

这个模式会匹配一个形如 /post/2023-01-01 的路径。由于参数没有命名,匹配到的值会按顺序存放在一个数字索引的数组中。

2.6. 通配符 (Wildcards)

path-to-regexp 提供了一个特殊的未命名参数作为通配符:*

  • 语法: *
  • 示例: /users/*

它本质上是 (.*) 的一个简写形式,用于匹配任意后缀。


掌握了这些语法,你就拥有了构建几乎任何复杂路由规则的能力。在下一章中,我们将从设计的角度,探讨 path-to-regexp 是如何将这些人类可读的语法规则,系统性地转换成机器可执行的正则表达式的。我们将会发现,这背后蕴含着经典的编译原理思想。

2. 核心概念:路径模式、参数与修饰符 has loaded