data-*属性命名必须全小写加连字符,js通过dataset访问时会自动转驼峰;写入需用setattribute才能持久化,dataset赋值仅修改内存副本;值恒为字符串,复杂类型须手动序列化与解析。

data-* 属性命名必须全小写加连字符,否则 JS 读不到
浏览器只解析符合规范的 data-* 属性:前缀 data- 后只能跟小写字母、数字、短横线(-),且不能以数字开头(除非用方括号访问)。写成 data-userId、data_user_id 或 data-UserID,DOM 根本不认——DevTools 里都看不到,element.dataset.userId 必然返回 undefined。
正确写法只有:data-user-id → element.dataset.userId,data-api-endpoint → element.dataset.apiEndpoint。含数字开头如 data-2024-report,只能用 element.dataset["2024Report"] 访问,点号语法失效。
读写必须用 dataset 或 setAttribute,别混用
dataset 是只读代理,不是真实 DOM 属性映射。写 el.dataset.foo = "bar" 只改内存副本,HTML 源码和 getAttribute("data-foo") 仍为旧值;刷新页面后就丢了。真要持久化,必须调用 setAttribute。
- 读取优先用:
if ("userId" in el.dataset) { id = el.dataset.userId; } - 写入必须用:
el.setAttribute("data-is-loading", "true")(自动转字符串) - 删属性用:
el.removeAttribute("data-is-pending"),别赋null或空字符串 - 混用风险:先
dataset.status = "done",再setAttribute("data-status", "fail"),两者值会不一致
dataset 值永远是字符串,复杂数据得手动序列化
无论你存的是布尔、数字还是对象,dataset 返回的全是字符串。写 data-count="42",读出来是 "42";写 data-config='{"theme":"dark"}',读出来是字符串,不是对象。
类型转换要自己来:
- 数字:
Number(el.dataset.count)或+el.dataset.count(避免parseInt("42px")截断) - 布尔:
el.dataset.isActive === "true"(Boolean("false")是true) - 对象:
JSON.parse(el.dataset.config || "{}"),必须加try-catch防止格式错误 - 服务端渲染时,JSON 字符串必须 HTML 实体编码,否则
JSON.parse()易报SyntaxError
data-* 不是状态管理工具,别当 React state 用
data-* 只适合存静态、低频、与渲染无关的上下文信息,比如埋点 ID、SKU 编号、API 路径片段。它不监听变更、不触发重绘、不支持响应式更新——DOM 改了,dataset 不会自动刷新,CSS 选择器也不会重新匹配。
常见误用:
- 用
data-is-loading="true"控制按钮禁用,却忘了同步设disabled属性 → 用户仍可点击 - 在 scroll 事件里高频读多个
dataset→ 触发重排,性能掉得快 - 存
data-user-preferences然后直接JSON.parse(el.dataset.userPreferences)→ 键名被驼峰转换(userPreferences ≠ user-preferences),解析失败 - 把 token、手机号塞进去 → 全暴露在源码和 DevTools 里,安全红线
真正容易被忽略的是:dataset 的“只读代理”本质——它不绑定 DOM,修改它不写回 HTML;若需服务端读取或 SEO 友好,必须用 setAttribute 写回。另外,高频读写场景下,应缓存解析结果,而不是反复访问 dataset。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











