data-*属性仅存字符串,存JSON需手动stringify,读取需parse并try/catch;驼峰转换有规则,混用setAttribute与dataset会导致不一致;敏感、动态、大数据不应存入。

data-* 属性根本存不了 JSON,只能存字符串
浏览器不会帮你做任何序列化或解析。你写 data-config='{"theme":"dark"}',DOM 里存的只是这个字符串;element.dataset.config 拿到的也还是字符串,不是对象。常见错误是直接访问 dataset.config.theme,结果报 Cannot read property 'theme' of undefined——因为 dataset.config 是字符串,不是对象。
必须手动处理:
- 写入前用
JSON.stringify(),不能直接赋对象 - 读取后用
JSON.parse(),且必须包try/catch(HTML 被篡改、服务端漏转义、字段含非法字符都会导致解析失败) - 空值要兜底:
JSON.parse(element.dataset.config || "{}")比JSON.parse(element.dataset.config)安全得多
命名和读取时驼峰转换容易出错
data-user-id 对应的是 dataset.userId,不是 dataset.user-id(语法错误),也不是 dataset["user-id"](返回 undefined)。这是 DOM 规范做的自动映射,写错就取不到值。
特别注意这些边界情况:
立即学习“前端免费学习笔记(深入)”;
- 属性名含数字开头,如
data-2024-start→ 必须用dataset["2024Start"],点号语法无效 -
data-api-url→dataset.apiUrl,不是dataset.apiUrl或dataset.APIUrl - 写成
data-userId或data_user_id,浏览器直接忽略,DevTools 里都看不到该属性
setAttribute 和 dataset 混用会导致状态不一致
dataset.xxx = "value" 看似生效,其实只是改了 JS 内存里的副本,DOM 属性没变;getAttribute("data-xxx") 仍返回旧值。真要持久化,必须用 setAttribute("data-xxx", value)。
典型陷阱:
- 先
el.dataset.foo = "a",再el.setAttribute("data-foo", "b")→ 后续el.dataset.foo还是"a",但el.getAttribute("data-foo")是"b" - 删除属性要用
el.removeAttribute("data-foo"),delete el.dataset.foo不可靠 - 读取优先用
el.dataset.xxx(语义清晰、自动驼峰),写入必须用setAttribute
哪些数据绝对不该塞进 data-* 里
data-* 只适合静态、轻量、非敏感的上下文信息。一旦越界,问题立刻暴露:
- 用户 token、手机号、邮箱等敏感字段:源码明文可见,DevTools 一点就开
- 购物车、权限列表、实时开关等动态状态:无法响应式更新,JS 改了 dataset 值,UI 不会重绘
- 大段 JSON(比如 >5KB 的配置或用户偏好):拖慢 DOM 解析,影响首屏性能
- 含
undefined、Date、function、循环引用的对象:JSON.stringify()直接静默丢弃或抛错
真正需要跨组件或跨生命周期共享的数据,应该走 localStorage、URL 参数、全局状态库,或者用 ID 查表——data-* 就是个临时贴纸,不是数据库。



















