Appearance
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\/([^\/]+?)\/?$/i2.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 是如何将这些人类可读的语法规则,系统性地转换成机器可执行的正则表达式的。我们将会发现,这背后蕴含着经典的编译原理思想。