html解析器按规则截断无引号属性值,仅纯字母数字、短横、下划线且无空格时合法;autocomplete值须严格匹配规范白名单并协同type使用;src/href等属性必须加双引号防截断与xss;data-属性名须全小写短横分隔,值恒为字符串。

HTML解析器怎么处理没引号的属性值
浏览器不会“补全”引号,而是按特定规则解析——遇到空格、>或/>就截断。比如<img src="logo.png" alt="Company" logo>会被拆成src="logo.png"、alt="Company",后面logo变成孤立文本,直接甩到DOM树外面。
这解释了为什么class=btn primary只生效btn,primary消失;也说明为什么data-id=123能跑通,但data-user-name=john doe会崩成data-user-name="john"加一堆乱文本。
- 只有纯字母数字+短横+下划线且无空格时,不加引号才被接受(如
id=main、type=checkbox) -
=前后不能有空格:class = "header"是合法的,但class= "header"在部分旧解析器里会失败 - 布尔属性如
disabled、required本身不带=,写成disabled=""或disabled="disabled"都算显式赋值,但语义一样
为什么autocomplete="Email"完全无效
这不是大小写问题,是解析器根本没把它当有效 token。WHATWG 规范明确定义了 autocomplete 值的白名单,Email不在其中,浏览器加载时直接跳过这个属性,相当于没写。
更隐蔽的是:即使你写了autocomplete="email",如果type不是email或text,Chrome 和 Safari 也会降权处理——它们依赖type和autocomplete协同匹配,单靠一个撑不起自动填充。
- 常见无效写法:
user-email、name(应拆为given-name/family-name)、password(必须用current-password或new-password) -
autocomplete="off"在密码字段上基本被忽略,Chrome ≥76 起主动无视它 - 动态渲染的表单,必须在初始 HTML 中就存在正确
autocomplete值,JS 后续setAttribute补不上
src和href路径缺失引号的实际后果
路径含空格、中文、括号或特殊字符时,不加引号几乎必然失败。例如<a href="/blog/2024/06/My" post.html></a>会被截断为href="/blog/2024/06/My",后面Post.html>变成文本节点,链接点不动。
服务器返回的 HTML 如果由模板拼接生成(比如 Node.js 的 res.send(<img src="%24%7Burl%7D">)),而url里带空格或&,不加引号会导致整个标签结构错位,甚至引发 XSS 风险(如url是" onload=alert(1)")。
- 永远用双引号包裹
src、href、data-*等所有属性值,别信“看起来能跑” - 服务端拼接前先对值做 HTML 实体编码:
encodeURIComponent不够,得用he.encode()或类似工具转义"、、<code>& - 相对路径开头的
/是根相对路径,不是文件系统根目录——这点和src是否加引号无关,但常被一起搞错
自定义data-属性在解析阶段的命名转换
HTML 解析器会把data-user-id转成dataset.userId,但这个转换只发生在 DOM 构建完成之后,不是解析 HTML 字符串时做的。也就是说,如果你用innerHTML写入<div data-user_id="123">(用了下划线),解析器会原样保留<code>data-user_id,但dataset对象里根本不会有userId或user_id——它只认短横分隔的命名。
更麻烦的是:一旦写错命名(比如data-UserID),不仅 JS 拿不到,连getAttribute('data-UserID')都返回null,因为解析器按小写归一化后存的是data-userid。
-
data-属性名必须全小写+短横,data-api-key✅,data_api_key❌,data-API-Key❌ - 值始终是字符串,哪怕你写
data-count=42,dataset.count拿到的也是"42",需手动parseInt - 不要用
data-传 JSON 字符串,结构复杂时改用<script type="application/json"></script>块











