根据html-parser.js源码,我们提取出12个核心正则表达式,本文先介绍和属性相关的下面2个正则表达式:
| 正则名称 | 类型 | 作用域 |
|---|---|---|
attribute | 静态定义 | 属性解析 |
dynamicArgAttribute | 静态定义 | 动态参数属性 |
(1) 属性提取高招
正则结构:
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
分层拆解:
^ # 起始位置
\s* # 允许前置空格
([^\s"'<>\/=]+) # 第1组:属性名(排除特殊字符)
(?:\s*(=)\s* # 非捕获组:等号
(?: # 值匹配分支
"([^"]*)"+ | # 双引号字符串
'([^']*)'+ | # 单引号字符串
([^\s"'=<>`]+) # 无引号值(不含空格)
)
)? # 属性值可选
完整案例:
v-model="message" → name: 'v-model', value: 'message'
:class="{ active }" → name: ':class', value: '{ active }'
@click.prevent="submit" → name: '@click.prevent', value: 'submit'
(2) 动态参数解析
正则结构:
const dynamicArgAttribute =
/^\s*(
(?:v-[\w-]+:|@|:|#) // 指令前缀
\[[^=]+?\] // 动态参数核心
[^\s"'<>\/=]* // 修饰符部分
)
(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+))?/x
分层拆解
^ # 起始位置
\s* # 允许前置空格
(
(?:v-[\w-]+:|@|:|#) # 第1组(非捕获): 指令前缀匹配
\[ # 匹配左方括号
[^=]+? # 动态参数内容(禁止包含等号)
\] # 匹配右方括号
[^\s"'<>\/=]* # 允许修饰符(如 .prop/.sync)
)
(?:\s*(=)\s* # 第2组(非捕获): 等号标识
(?: # 值匹配分支
"([^"]*)"+ | # 第3组: 双引号字符串
'([^']*)'+ | # 第4组: 单引号字符串
([^\s"'=<>`]+) # 第5组: 无引号值
)
)? # 属性值可选
捕获组说明
| 组号 | 匹配内容 | 示例输入 | 捕获结果 |
|---|---|---|---|
| 1 | 完整动态属性名 | :[dynProp].sync | :[dynProp].sync |
| 2 | 等号标识符 | = | = |
| 3 | 双引号属性值 | "value" | value |
| 4 | 单引号属性值 | 'value' | value |
| 5 | 无引号属性值 | value | value |
完整案例解析
1. 基础动态参数
<component :[dynamicProp]="value" />
匹配结果:
- 组1:
:[dynamicProp] - 组2:
= - 组3:
"value"→value
2. 带修饰符的事件
<button @[eventName].prevent="handleEvent" />
匹配结果:
- 组1:
@[eventName].prevent - 组2:
= - 组3:
"handleEvent"→handleEvent
3. 无值动态指令
<div #[slotName] />
匹配结果:
- 组1:
#[slotName] - 组2:
undefined(无等号) - 值捕获组:
undefined
特殊场景验证
1. 动态参数含特殊字符
<input :[data-${type}]="val" />
匹配结果:
- 组1:
:[data-${type}] - 组3:
"val"→val
2. 多级动态参数
<menu :[items[0].key]="firstItem" />
匹配失败:
- 因
[^=]+?禁止包含等号,items[0].key合法 - 若参数含等号(非法情况):
:[invalid=prop]→ 触发解析错误
(下篇预告:深度解析 Vue2 html-parser.js标签相关正则表达式 )