(1) 文档类型声明(doctype)
正则表达式:
const doctype = /^<!DOCTYPE [^>]+>/i
分层拆解
^ # 起始位置
<!DOCTYPE # 固定文档类型声明头
[^>]+ # 匹配除>外的任意字符(文档类型详细内容)
> # 结束符
修饰符:i(忽略大小写,兼容<!doctype>写法)
示例场景
| 输入示例 | 匹配结果 |
|---|---|
<!DOCTYPE html> | 完整匹配 |
<!doctype HTML PUBLIC "-//W3C..."> | 完整匹配(不区分大小写) |
<![if IE]> | 不匹配(非DOCTYPE) |
(2) HTML注释(comment)
正则表达式:
const comment = /^<!\--/
分层拆解
^ # 起始位置
<!\\- # 匹配注释起始符<!--(注意转义)
示例场景
| 输入示例 | 匹配结果 |
|---|---|
<!-- 注释内容 --> | 匹配前4字符(<!--) |
<div><!-- text --> | 不匹配(非起始位置) |
(3) 条件注释(conditionalComment)
正则表达式:
const conditionalComment = /^<!\[/
分层拆解
^ # 起始位置
<!\\[ # 匹配条件注释起始符<![
示例场景
| 输入示例 | 匹配结果 |
|---|---|
<![if IE]> | 匹配前3字符(<![) |
<![endif]> | 匹配前3字符 |
<!--[if IE]> | 不匹配(非起始位置) |
编码字符处理系统
(4) 基础编码字符(encodedAttr)
正则表达式:
const encodedAttr = /&(?:lt|gt|quot|amp|#39);/g
分层拆解
& # 编码起始符
(?: # 非捕获组(编码类型)
lt|gt| # < 或 >
quot|amp| # " 或 &
#39 # '
)
; # 结束符
示例解码映射
| 编码 | 解码字符 |
|---|---|
< | < |
> | > |
" | " |
& | & |
' | ' |
(5) 含换行符的编码字符(encodedAttrWithNewLines)
正则表达式:
const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#39|#10|#9);/g
扩展功能
#10 # 换行符(\n)
#9 # 制表符(\t)
使用场景:
<pre> 内容 </pre> → 保留换行格式
纯文本元素解析
(6) 堆叠标签内容提取(reStackedTag)
动态构建正则:
new RegExp(
'([\\s\\S]*?)(</' + // 第1组:任意字符(非贪婪)
stackedTag + // 当前处理的标签名(如script)
'[^>]*>)', // 结束标签部分
'i' // 忽略大小写
)
分层拆解
([\\s\\S]*?) # 第1组:匹配任意内容(包括换行)
(</ # 结束标签起始符
${stackedTag} # 当前标签名(动态插入)
[^>]*> # 标签结束符(允许属性等非法内容)
) # 第2组:完整结束标签
捕获组说明
| 组号 | 匹配内容 | 示例输入 | 捕获结果 |
|---|---|---|---|
| 1 | 标签间文本内容 | <script>alert(1)</script> | alert(1) |
| 2 | 结束标签 | </script> | </script> |
实战案例
<script>
console.log("</script>") // 需要转义
</script>
匹配流程:
([\\s\\S]*?)捕获所有内容直到结束标签
→\n console.log("</script>") // 需要转义\n(</script>)捕获结束标签
设计亮点总结
| 正则 | 核心目标 | 容错机制 |
|---|---|---|
doctype | 快速跳过文档类型声明 | 不区分大小写 |
comment | 识别注释起始位置 | 精准定位避免误判 |
reStackedTag | 安全提取纯文本元素内容 | 动态标签名匹配 |
通过这组正则表达式的协作,Vue2实现了:
✅ 精准的模板结构解析
✅ HTML实体安全解码
✅ 纯文本元素的完整内容提取
✅ 对历史遗留语法(如IE条件注释)的兼容处理
这些设计保障了模板编译器在复杂场景下的稳定性和高性能,是Vue响应式系统的基石之一。