data-*属性必须小写连字符命名,dataset自动转驼峰且仅支持字母数字和连字符;值恒为字符串,需手动类型转换;css中attr()仅限content且需引号;innerhtml不反映dataset实时值。

data-\* 属性必须用小写连字符命名
浏览器只认 data- 开头、后面跟小写字母和连字符的属性名,比如 data-user-id 合法,data-userId 或 data-UserId 会被忽略——DOM API 读不到,CSS 伪类也匹配不上。
常见错误现象:element.dataset.userId 返回 undefined,但 element.getAttribute('data-userId') 能取到值(因为原生属性没校验规则,但 dataset 映射是严格转换的)。
-
data-user-id→dataset.userId(自动转驼峰) -
data-api-url→dataset.apiUrl -
data-123或data-_id都非法,会被浏览器静默丢弃
dataset 读写不实时同步到 HTML 字符串
element.dataset.foo = 'bar' 会更新 DOM 属性,但反过来,直接 element.setAttribute('data-foo', 'baz') 也会同步进 dataset。问题在于:如果用 JS 修改了 dataset,再用 innerHTML 读取父元素内容,新值不会出现在字符串里——dataset 是内存映射,不是源 HTML 的镜像。
使用场景:服务端渲染后前端补数据,或调试时想看当前 data 值是否生效,别依赖 innerHTML 检查,改用 getAttribute 或直接查 dataset。
立即学习“前端免费学习笔记(深入)”;
- ✅ 安全读写:
el.dataset.count = '5'; console.log(el.dataset.count); // '5' - ⚠️ 不可靠检查:
el.parentElement.innerHTML.includes('data-count="5"')可能为 false - ✅ 正确验证:
el.hasAttribute('data-count') && el.getAttribute('data-count') === '5'
data-\* 值始终是字符串,类型要自己转
哪怕你在 HTML 里写 data-price="9.99" 或 data-active="true",通过 dataset.price 拿到的永远是字符串 "9.99" 和 "true",不是数字或布尔值。
性能影响很小,但逻辑错位风险高:比如 if (el.dataset.active) 对 "false" 也返回 true,因为非空字符串是真值。
- 数字:用
Number(el.dataset.price)或一元加号+el.dataset.price - 布尔:用
el.dataset.active === 'true',别用Boolean(el.dataset.active) - JSON 数据:建议存为
data-config='{"mode":"dev","timeout":3000}',然后JSON.parse(el.dataset.config)
CSS 里用 attr() 读 data-\* 要加引号且仅限 content
attr(data-foo) 只能在 ::before/::after 的 content 属性里用,不能用于 color、width 等其他样式。而且值必须是纯文本,不能参与计算。
容易踩的坑:有人想用 data-theme="dark" 控制背景色,结果写 background: attr(data-theme);——这语法无效,浏览器直接忽略整条声明。
- ✅ 有效:
.btn::after { content: attr(data-count); } - ❌ 无效:
.card { background: attr(data-theme); } - ⚠️ 注意:
attr(data-id)返回的是字符串,即使原值是数字,也不能直接用于 calc()
data-\* 看似简单,但命名规则、类型隐式转换、CSS 使用边界这几个地方,稍微松懈就掉坑里。尤其是前后端协作时,后端模板拼的 data 属性名大小写一错,前端 JS 就拿不到——这种问题很难一眼看出来。











