根据html-parser.js源码,我们提取出12个核心正则表达式,本文先介绍和标签相关的下面3个正则表达式:
| 正则名称 | 类型 | 作用域 |
|---|---|---|
startTagOpen | 动态构建 | 开始标签 |
startTagClose | 静态定义 | 开始标签闭合 |
endTag | 动态构建 | 结束标签 |
XML命名规则解析
(1) 基础标签名(ncname)
正则结构:
const ncname =
`[a-zA-Z_] // 首字符规则
[\\-\\.0-9_a-zA-Z // 后续字符基础集
${unicodeRegExp.source} // Unicode扩展支持
]*` // 允许重复
分层拆解
[ # 字符集开始
a-zA-Z_ # 首字符:字母或下划线
][ # 后续字符集
\\-\\. # 允许连字符(-)和点号(.)
0-9_a-zA-Z # 数字、下划线、字母
\u00B7\u00C0-\u00D6... # Unicode字符(具体由unicodeRegExp定义)
]* # 重复0次或多次
捕获组说明
| 元素 | 匹配规则 | 合法示例 | 非法示例 |
|---|---|---|---|
| 首字符 | 必须为字母或下划线 | <my-component> | <3d-model> |
| 后续字符 | 可包含数字/连字符/点号/Unicode | <图标-列表> | <a#section> |
| Unicode支持 | 包含中文/日文/韩文等非ASCII字符 | <東京_駅> | <^alert> |
(2) 带命名空间的标签名(qnameCapture)
正则结构:
const qnameCapture =
`( # 开始捕获组
(?:${ncname}\\:)? # 可选命名空间
${ncname} # 基础标签名
)`
分层拆解
( # 第1组(总捕获)
(?: # 非捕获组(命名空间部分)
[a-zA-Z_][...] # ncname定义的合法名称
\\: # 命名空间分隔符(:)
)? # 命名空间可选
[a-zA-Z_][...] # 基础标签名(ncname规则)
)
捕获案例解析
| 输入示例 | 匹配结果 | 解析说明 |
|---|---|---|
<div> | div | 无命名空间 |
<svg:circle> | svg:circle | 带命名空间 |
<foo:bar-baz> | foo:bar-baz | 命名空间+复合名称 |
(3) 开始标签解析(startTagOpen)
动态构建正则:
const startTagOpen = new RegExp(`^<${qnameCapture}`)
// 等效正则:/^<((?:[a-zA-Z_][...]*\:)?[a-zA-Z_][...]*)/
分层拆解
^< # 起始符和标签开始
( # 第1组捕获(完整标签名)
(?: # 非捕获组(命名空间)
[a-zA-Z_][...]:
)?
[a-zA-Z_][...] # 基础标签名
)
实战匹配流程
<input> → 匹配组1: "input"
<svg:rect> → 匹配组1: "svg:rect"
<ns:data-grid> → 匹配组1: "ns:data-grid"
设计亮点总结
- XML规范兼容:严格遵循XML命名规则
- 首字符禁止数字
- 允许命名空间语法
- Unicode支持:通过
unicodeRegExp扩展多语言支持// unicodeRegExp包含的典型字符范围 \u00B7(·)、\u4E00-\u9FFF(中日韩文字)等 - 性能优化:
- 使用预定义
ncname避免重复编写复杂规则 - 动态构建正则减少模式冗余
- 使用预定义
与HTML5的差异处理
| 特性 | Vue2实现 | HTML5规范 | 原因 |
|---|---|---|---|
| 标签首字符 | 必须字母/下划线 | 允许自定义元素 | 兼容XML解析规则 |
| 命名空间 | 显式:分隔 | 无原生支持 | 保持模板语法一致性 |
| 标签大小写 | 严格区分 | 不区分 | 遵循XML特性 |
错误检测案例
<3d-model> → 解析失败(首字符为数字)
<foo:> → 解析失败(命名空间后无名称)
<data:list> → 合法(需确保data命名空间已定义)
在AST生成中的作用
graph TD
A[模板字符串] --> B{startTagOpen匹配}
B -->|成功| C[记录标签名和位置]
C --> D[进入属性解析流程]
B -->|失败| E[按文本节点处理]
这些正则的精准匹配为后续操作奠定基础:
- 确定元素类型(标准HTML标签/自定义组件)
- 触发对应的AST节点生成逻辑
- 影响虚拟DOM的diff算法策略
通过这种严格而灵活的设计,Vue2的模板编译器既能处理现代Web开发中的复杂场景,又保持了与传统XML生态的良好兼容性。