data-*属性仅适合存静态、轻量、非敏感的元数据,如data-item-id="42";命名须全小写加连字符,读写须用getAttribute/setAttribute,值恒为字符串,不具响应式能力,不可替代状态管理。

HTML 全局属性中,data-* 是唯一被标准明确允许用于存储自定义数据的机制;但它不是状态容器,只适合存静态、轻量、非敏感的元数据——比如 data-item-id="42" 或 data-modal-trigger="click",而非用户偏好、token 或组件状态。
data-* 属性名写错,JS 就读不到
浏览器对 data-* 属性名校验极严:前缀后必须全小写 + 连字符,不能有大写、下划线、点号或数字开头(数字开头虽合法但访问受限)。写错就静默忽略,DOM 里根本不存在该属性。
-
data-user-id→ 正确,JS 中通过el.dataset.userId访问 -
data-userId、data_user_id、data-UserID→ 全部无效,el.dataset.userId返回undefined -
data-2024-start-date→ 合法,但只能用el.dataset["2024StartDate"],el.dataset.2024StartDate是语法错误 - 连字符过多如
data-foo--bar会被转成fooBar,语义模糊,不推荐
dataset 是只读映射,改值必须用 setAttribute
dataset 是 DOM 解析时生成的一次性字符串快照(DOMStringMap),不是双向绑定。赋值操作不会写入 DOM,也不会触发 HTML 变化或 CSS 选择器重匹配。
-
el.dataset.foo = "bar"→ 只改内存副本,el.getAttribute("data-foo")仍返回旧值 - 真正写入 DOM 的唯一方式:
el.setAttribute("data-foo", "bar") - 删除必须用:
el.removeAttribute("data-foo"),delete el.dataset.foo无效 - 混用风险:先
dataset.foo = "a",再setAttribute("data-foo", "b"),后续dataset.foo仍返回"a"(缓存未刷新)
所有值都是字符串,类型转换必须手动做
哪怕 HTML 写 data-count="42" 或 data-active="false",JS 读到的仍是字符串 "42" 和 "false"。自动类型转换不存在,依赖它会出逻辑 bug。
立即学习“前端免费学习笔记(深入)”;
-
el.dataset.count + 1→ 得到"421"(字符串拼接),应写+el.dataset.count + 1或Number(el.dataset.count) + 1 -
if (el.dataset.active)→ 在data-active="false"时仍为true(非空字符串恒真),正确判断是el.dataset.active === "true" - 存 JSON:用
el.setAttribute("data-config", JSON.stringify(obj));取时必须JSON.parse(el.getAttribute("data-config") || "{}"),不能用el.dataset.config(驼峰转换可能错位键名)
CSS 选择器匹配 data-* 要加引号,且不能替代响应式状态
在 CSS 中用属性选择器匹配 data-* 值时,值含字母数字外字符(如连字符、空格)必须加引号,否则规则不生效;更重要的是,data-* 变更不会触发重绘或响应式更新。
-
[data-status=active]→ 不安全,data-status="loading-failed"不会匹配 - 应写:
[data-status="active"]或[data-status~="active"](空格分隔值) -
data-loaded="true"改成"false"后,CSS 类不会自动切换,class才是渲染层的可控入口 - 需要跨刷新持久化的数据,该交给
localStorage或后端 API,data-*刷新后只是原始 HTML 里的字符串
最常被忽略的一点:你看到 dataset.xxx 有值,不代表它真在 DOM 里——可能只是之前某次 setAttribute 留下的残留;验证是否写入成功,永远看 el.getAttribute("data-xxx"),而不是信 dataset 的缓存。



















