应直接用 getAttribute() 和 setAttribute() 操作 data 属性,因 dataset 仅映射符合 data-xxx-yyy 格式的属性,对含数字、大写、下划线等不规范命名静默忽略,且其赋值不真正更新 DOM;dataset 值恒为字符串,需手动类型转换;CSS 选择器必须加引号确保匹配准确。

直接用 getAttribute() 读、setAttribute() 写,别依赖 dataset 赋值——它不真正更新 DOM,且对命名不规范的属性静默失败。
为什么 dataset.xxx 经常读不到值
浏览器只把符合 data-xxx-yyy(全小写 + 连字符)格式的属性映射进 dataset。一旦出现数字开头、大写字母或下划线,dataset 就完全忽略,也不报错:
-
data-userId→dataset.userId返回undefined(含大写) -
data_user_id→dataset.userId或dataset._userId都是undefined(下划线不转换) -
data-2024-start→dataset["2024Start"]可读,但dataset.2024Start是语法错误 -
data-UID→dataset.uid不生效,必须用getAttribute("data-UID")
而 getAttribute("data-xxx") 直接读原始 HTML 字符串,无转换、无过滤、不丢值,是最稳的兜底方式。
修改 data 属性必须用 setAttribute,dataset 赋值无效
dataset 是只读映射,不是双向绑定。执行 el.dataset.status = "done" 看似生效,但:
立即学习“前端免费学习笔记(深入)”;
-
getAttribute("data-status")仍返回旧值或null - CSS 属性选择器如
[data-status="done"]不会重新匹配 - 其他 JS 代码调用
getAttribute也读不到新值 - 刷新页面后,该赋值彻底丢失
真正写入 DOM 的唯一方式是:el.setAttribute("data-status", "done")。删除同理:el.removeAttribute("data-status"),delete el.dataset.status 完全没用。
值永远是字符串,类型转换不能省
无论你在 HTML 里写 data-count="42" 还是 data-active="false",读出来都是字符串:
-
el.dataset.count + 1得到"421",不是43;应写成+el.dataset.count + 1或Number(el.dataset.count) + 1 -
if (el.dataset.active)在data-active="false"时仍为真(非空字符串转布尔为真);正确判断是el.dataset.active === "true" - 存 JSON 推荐用
JSON.parse(el.getAttribute("data-config")),而非JSON.parse(el.dataset.config)——后者因驼峰转换可能取错键名(如data-user-preferences→dataset.userPreferences)
CSS 用 [data-*] 选择器时必须加引号
不加引号的写法如 [data-state=active] 在值含空格、点、括号或连字符时会解析失败,且部分浏览器直接忽略:
- ❌
[data-loading=true]—— 值为"loading"时不匹配 - ✅
[data-loading="loading"]—— 明确、安全、全浏览器兼容 - ✅
[data-path^="/admin"](开头匹配)、[data-variant~="primary"](空格分隔单词匹配)也都需引号包裹值
JS 修改属性后样式自动生效,但前提是用了 setAttribute(或 dataset 的写入触发了底层同步),否则 CSS 引擎看不到变化。



















