HTML5 自定义属性 data-*:别再把数据塞进 class 里了!

前言:由于"无处安放"而引发的混乱

在 HTML5 普及之前,前端开发者为了在 DOM 元素上绑定一些数据(比如用户 ID、商品价格、状态码),可谓是八仙过海,各显神通:

  1. 隐藏域流派 :到处塞 <input type="hidden" value="123">,导致 HTML 结构像个堆满杂物的仓库。
  2. Class 拼接流派<div class="btn item-id-8848">,然后用正则去解析 class 字符串提取 ID。这简直是在用 CSS 类名当数据库用,类名听了都想离家出走。
  3. 自定义非标属性流派 :直接写 <div my_id="123">。虽然浏览器大多能容忍,但这就好比在公共泳池里裸泳------虽然没人抓你,但不合规矩且看着尴尬。

直到 HTML5 引入了 data-* 自定义数据属性,这一切终于有了"官方标准"。


第一阶段:基础------它长什么样?

data-* 属性允许我们在标准 HTML 元素中存储额外的页面私有信息。

1. HTML 写法

语法非常简单:必须以 data- 开头,后面接上你自定义的名称。

codeHtml

xml 复制代码
<!-- ❌ 错误示范:不要大写,不要乱用特殊符号 -->
<div data-User-Id="1001"></div> 

<!-- ✅ 正确示范:全小写,连字符连接 -->
<div 
  id="user-card"
  data-id="1001" 
  data-user-name="juejin_expert" 
  data-value="99.9"
  data-is-vip="true"
>
  用户信息卡片
</div>

2. CSS 中的妙用

很多人以为 data-* 只是给 JS 用的,其实 CSS 也能完美利用它。

场景一:通过属性选择器控制样式

codeCSS 复制代码
/* 当 data-is-vip 为 "true" 时,背景变金 */
div[data-is-vip="true"] {
  background: gold;
  border: 2px solid orange;
}

场景二:利用 attr() 显示数据

这是一个非常酷的技巧,可以用来做 Tooltip 或者计数器显示。

codeCSS 复制代码
div::after {
  /* 直接把 data-value 的值显示在页面上 */
  content: "当前分值: " attr(data-value);
  font-size: 12px;
  color: #666;
}

第二阶段:进阶------JavaScript 如何读写?

这才是重头戏。在 JS 中操作 data-* 有两种方式:传统派现代派

1. 传统派:getAttribute / setAttribute

这是最稳妥的方法,兼容性最好(虽然现在也没人要兼容 IE6 了)。

codeJavaScript 复制代码
const el = document.getElementById('user-card');

// 读取
const userId = el.getAttribute('data-id'); // "1001"

// 修改
el.setAttribute('data-value', '100');

特点 :读出来永远是字符串。哪怕你存的是 100,取出来也是 "100"。

2. 现代派:dataset API (推荐 ✨)

HTML5 为每个元素提供了一个 dataset 对象(DOMStringMap),它将所有的 data-* 属性映射成了对象的属性。

这里有个大坑(或者说是规范),请务必注意:

HTML 中的 连字符命名 (kebab-case) 会自动转换为 JS 中的 小驼峰命名 (camelCase)

codeJavaScript 复制代码
const el = document.getElementById('user-card');

// 1. 访问 data-id
console.log(el.dataset.id); // "1001"

// 2. 访问 data-user-name (注意变身了!)
console.log(el.dataset.userName); // "juejin_expert"
// ❌ el.dataset.user-name 是语法错误
// ❌ el.dataset['user-name'] 是 undefined

// 3. 修改数据
el.dataset.value = "200"; 
// HTML 会自动变成 data-value="200"

// 4. 删除数据
delete el.dataset.isVip;
// HTML 中的 data-is-vip 属性会被移除

💡 敲黑板 :dataset 里的属性名不支持大写字母。如果你在 HTML 里写 data-MyValue="1", 浏览器会强制转为小写 data-myvalue,JS 里就得用 dataset.myvalue 访问。所以,HTML 里老老实实全小写吧。


第三阶段:深入------类型陷阱与性能权衡

1. 一切皆字符串

不管你赋给 dataset 什么类型的值,最终都会被转为字符串。

codeJavaScript 复制代码
el.dataset.count = 100;        // HTML: data-count="100"
el.dataset.active = true;      // HTML: data-active="true"
el.dataset.config = {a: 1};    // HTML: data-config="[object Object]" -> 灾难!

避坑指南

  • 如果你要存数字,取出来时记得 Number(el.dataset.count)。
  • 如果你要存布尔值,判断时不能简单用 if (el.dataset.active),因为 "false" 字符串也是真值!要用 el.dataset.active === 'true'。
  • 千万不要试图在 data-* 里存复杂的 JSON 对象。如果非要存,请使用 JSON.stringify(),但在 DOM 上挂载大量字符串数据会影响性能。

2. 性能考量

  • 读写速度:dataset 的访问速度在现代浏览器中非常快,但在极高频操作下(比如每秒几千次),直接操作 JS 变量肯定比操作 DOM 快。
  • 重排与重绘:修改 data-* 属性会触发 DOM 变更。如果你的 CSS 依赖属性选择器(如 divdata-status="active"),修改属性可能会触发页面的重排(Reflow)或重绘(Repaint)。

第四阶段:实战------优雅的事件委托

data-value 最经典的用法之一就是在列表项的事件委托中。

需求:点击列表中的"删除"按钮,删除对应项。

codeHtml 复制代码
<ul id="todo-list">
  <li>
    <span>学习 HTML5</span>
    <!-- 把 ID 藏在这里 -->
    <button class="btn-delete" data-id="101" data-action="delete">删除</button>
  </li>
  <li>
    <span>写掘金文章</span>
    <button class="btn-delete" data-id="102" data-action="delete">删除</button>
  </li>
</ul>
codeJavaScript 复制代码
const list = document.getElementById('todo-list');

list.addEventListener('click', (e) => {
  // 利用 dataset 判断点击的是不是删除按钮
  const { action, id } = e.target.dataset;

  if (action === 'delete') {
    console.log(`准备删除 ID 为 ${id} 的条目`);
    // 这里发送请求或操作 DOM
    // deleteItem(id);
  }
});

为什么这么做优雅?

你不需要给每个按钮都绑定事件,也不需要去分析 DOM 结构(比如 e.target.parentNode...)来找数据。数据就在元素身上,唾手可得。


总结与"禁忌"

HTML5 的 data-* 属性是连接 DOM 和数据的一座轻量级桥梁。

什么时候用?

  • 当需要把少量数据绑定到特定 UI 元素上时。
  • 当 CSS 需要根据数据状态改变样式时。
  • 做事件委托需要传递参数时。

什么时候别用?(禁忌)

  1. 不要存储敏感数据:用户可以直接在浏览器控制台修改 DOM,千万别把 data-password 或 data-user-token 放在这。
  2. 不要当数据库用:别把几 KB 的 JSON 数据塞进去,那是 JS 变量或者是 IndexDB 该干的事。
  3. SEO 无用:搜索引擎爬虫通常不关心 data-* 里的内容,重要的文本内容还是要写在标签里。

最后一句

代码整洁之道,始于不再乱用 Class。下次再想存个 ID,记得想起那个以 data- 开头的帅气属性。

Happy Coding! 🚀

相关推荐
mldong6 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排6 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60617 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角8 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!8 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰8 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi10 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen11 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马11 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu11 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss