应使用 setattribute() 更新 data- 属性,因 dataset 赋值仅操作内存副本、不写 dom;data- 属性名须全小写加连字符(如 data-user-id),非法命名(如 data-userid)将被忽略;dataset 是只读映射,修改无效,删除须用 removeattribute();值恒为字符串,需手动类型转换;存取 json 应用 setattribute() 与 getattribute() 配合 json.stringify/parse;ssr 场景下命名与初始写入必须在模板层严格规范。

直接用 setAttribute() 更新,别碰 dataset 赋值——它不写 DOM,只改内存副本,刷新就丢。
data- 属性名不合法,更新后根本不存在
浏览器只解析符合规范的 data- 属性:全小写 + 连字符。写成 data-userId、data_user_id、data-UserID 或 data-2024-start(数字开头)都会被忽略——DOM 树里压根没这属性,setAttribute() 也白搭。
- 正确写法只有:
data-user-id、data-api-endpoint、data-1st-load -
data-1st-load这种数字开头的,必须用el.setAttribute('data-1st-load', 'true'),不能依赖dataset["1stLoad"]去“读”,因为先得存在才能读 - 服务端渲染时若拼错命名,客户端 JS 执行
setAttribute也不会修复 HTML 源码里的错误,只会新增一个合法属性(比如你误写data-userId,又执行setAttribute('data-user-id', '123'),结果 DOM 上同时存在两个属性)
用 dataset.xxx = 'val' 看似生效,实际没更新 DOM
dataset 是只读映射,不是双向绑定。执行 el.dataset.status = "loading" 后,el.getAttribute('data-status') 仍返回 null 或旧值,CSS 选择器如 [data-status="loading"] 也匹配不到,事件监听器或框架的 attributeChangedCallback 更不会触发。
- 真正持久化更新的唯一方式是:
el.setAttribute('data-status', 'loading') - 删除必须用:
el.removeAttribute('data-status'),delete el.dataset.status完全无效 - 混用会出问题:先
dataset.foo = "a",再setAttribute('data-foo', 'b'),后续dataset.foo还是"a"(缓存未刷新),而getAttribute('data-foo')返回"b"—— 两者已不一致
值永远是字符串,类型转换必须手动做
哪怕你在 HTML 里写 data-count="42" 或 data-active="false",JS 里拿到的全是字符串。不处理就参与运算或判断,结果必然错。
-
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"或el.getAttribute('data-active') === "true" - 存 JSON 必须用
el.setAttribute('data-config', JSON.stringify(obj));取时用JSON.parse(el.getAttribute('data-config') || '{}'),不能用el.dataset.config(驼峰转换可能错位键名,且无法保证原始大小写)
最常被忽略的一点:dataset 的行为在 SSR 场景下更危险——服务端输出的 HTML 中,dataset 对象在首次 JS 执行前不可读;而 getAttribute() 虽然能读,但若服务端拼错了 data- 名,客户端也没法靠 JS “纠正”源码。命名规范和首次写入方式,必须从模板层就卡死。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











