data-* 属性写上去容易,用起来最容易出错的一点是:它存的是字符串,既不代表布尔值,也不参与任何响应式更新。把状态放在这里,页面自然是静止的。

错误写法与正确写法
// 误把字符串当布尔用
star.dataset.active = true;
if (star.dataset.active) { /* 字符串 'false' 也是真值 */ }
// 显式赋值字符串后做严格比较
star.dataset.active = isActive ? 'true' : 'false';
if (star.dataset.active === 'true') { /* 结果确定 */ }
属性值经 dataset 写出后统一转成字符串,布尔值 true 与 false 分别落成 “true” 与 “false”,两者在条件判断里都是真值。
数值要做转换
const count = Number(card.dataset.count ?? 0);
if (count > 3) { /* 用数字比较 */ }
直接比较字符串会出现 '10' < '9' 这类字典序结果。读取数值先转 Number,缺失值给默认值。
三点认知
- 属性不担任状态存储。改属性值不会触发任何框架的重新渲染,也不会引起超出 CSS 选择器范围的重绘。
- 要做视觉切换时写在样式钩子层。类名与属性选择器二选一,属性选择器命中
[data-active="true"]即可。 - 跨页面或跨会话的状态交给持久层。轮到服务端、localStorage 或 BroadcastChannel 出场时,data-* 只保留渲染所需的那一份。
属性与 CSS 的配合
.star[data-active="true"] { color: #f5a623; }
.star[data-active="false"] { color: #9aa0a6; }
取消 setAttribute(‘hidden’) 之外还要确认没有被 display 或 visibility 规则覆盖,这一点在组件库里最常踩。
可靠顺序
- 状态放在 JS 变量或框架 store;
- 需要样式联动时同步到属性或类名;
- 需要持久化时再写 localStorage 或提交服务端;
- 不要反向由属性值推导状态。
