<p>data-* 属性仅适用于存储静态、轻量、非敏感的上下文信息,不能替代状态管理;必须全小写加连字符命名(如data-user-id),数字开头需用方括号访问;dataset是只读快照,修改需setAttribute;存JSON须手动序列化/解析并try/catch;敏感数据严禁使用;仅在customElements中配合observedAttributes可控使用。</p>

data-* 属性不能替代状态管理,它只适合存静态、轻量、非敏感的上下文信息。想靠 data-user-id 或 dataset.active 实现组件级响应式状态同步?行不通。
为什么 dataset 读出来总是 undefined?
根本原因不是 JS 写错了,是 HTML 属性名不符合规范,浏览器压根没解析。
-
data-userId、data_user_id、data-UserID全部无效 —— 只有全小写 + 连字符才被识别 - 正确写法:
data-user-id→ JS 中读作element.dataset.userId - 数字开头的属性如
data-2024-year,必须用element.dataset["2024Year"]访问,点号语法会报错 - 后端模板拼接时混用下划线或驼峰,前端永远取不到值
dataset.xxx = "value" 看似生效,其实没改 DOM
dataset 是只读代理,不是双向绑定。它只是初始化时对 data-* 的一次快照映射。
- 执行
el.dataset.foo = "new"后,el.getAttribute('data-foo')仍返回旧值 - 真正写入 DOM 的唯一方式:用
el.setAttribute('data-foo', 'value') - 删除必须用
el.removeAttribute('data-foo'),不能靠delete el.dataset.foo - 混用会导致缓存不一致:先赋值
dataset.foo,再setAttribute,后续读dataset.foo还是旧值
data-* 存 JSON 的典型翻车现场
可以存,但必须手动序列化/解析,且极易因格式或安全问题崩掉。
立即学习“前端免费学习笔记(深入)”;
- 写入时:用
JSON.stringify(),别直接塞对象字面量 - 读取时:必须
try/catch包裹JSON.parse(),否则data-config='{"theme":}'这种坏 JSON 会让整个组件初始化失败 -
data-config='{"user":{"id":1024}}'→JSON.parse(el.dataset.config).user.id得到的是字符串"1024",不是数字 - 敏感数据(token、密码、用户偏好)绝不能走
data-*,XSS 风险极高
什么场景下真能用 data-* 做状态桥接?
只有配合 customElements + attributeChangedCallback 才算“可控的手动追踪”。
- 必须在
static get observedAttributes()里声明'user-id'(注意:不是'data-user-id') -
constructor()里不能直接读dataset,此时子节点未挂载,shadowRoot不可用 - 真正参与状态驱动渲染的原生入口极少:
id、class、hidden、tabindex—— 它们变更会触发重绘或焦点流变化 -
class适合表达有限布尔态(loading、error),但无法承载结构化数据
data-* 的边界非常清晰:它是静态上下文传递通道,不是状态总线。一旦你开始给它加监听、做深 clone、试图让它响应式,就该换方案了 —— 不是框架太重,是你正在用螺丝刀拧螺母。



















