光明吉祥 發表於 2026-2-24 13:38:00

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

<h1 data-id="heading-0">🧑‍💻 写在开头</h1>
<p>点赞 + 收藏 === 学会🤣🤣🤣</p>
<div>
<div>
<h2 data-id="heading-0">前言:由于“无处安放”而引发的混乱</h2>
<p>在 HTML5 普及之前,前端开发者为了在 DOM 元素上绑定一些数据(比如用户 ID、商品价格、状态码),可谓是八仙过海,各显神通:</p>
<ol>
<li><strong>隐藏域流派</strong>:到处塞&nbsp;<code>&lt;input type="hidden" value="123"&gt;</code>,导致 HTML 结构像个堆满杂物的仓库。</li>
<li><strong>Class 拼接流派</strong>:<code>&lt;div class="btn item-id-8848"&gt;</code>,然后用正则去解析 class 字符串提取 ID。这简直是在用 CSS 类名当数据库用,类名听了都想离家出走。</li>
<li><strong>自定义非标属性流派</strong>:直接写&nbsp;<code>&lt;div my_id="123"&gt;</code>。虽然浏览器大多能容忍,但这就好比在公共泳池里裸泳——虽然没人抓你,但不合规矩且看着尴尬。</li>
</ol>
<p>直到 HTML5 引入了&nbsp;<strong>data-</strong>* &nbsp;自定义数据属性,这一切终于有了“官方标准”。</p>
<hr>
<h2 data-id="heading-1">第一阶段:基础——它长什么样?</h2>
<p>data-*&nbsp;属性允许我们在标准 HTML 元素中存储额外的页面私有信息。</p>
<h3 data-id="heading-2">1. HTML 写法</h3>
<p>语法非常简单:必须以&nbsp;data-&nbsp;开头,后面接上你自定义的名称。</p>
</div>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;!-- ❌ 错误示范:不要大写,不要乱用特殊符号 --&gt;
&lt;div data-User-Id="1001"&gt;&lt;/div&gt;

&lt;!-- ✅ 正确示范:全小写,连字符连接 --&gt;
&lt;div
id="user-card"
data-id="1001"
data-user-name="juejin_expert"
data-value="99.9"
data-is-vip="true"
&gt;
用户信息卡片
&lt;/div&gt;</pre>
</div>
<h3 data-id="heading-3">2. CSS 中的妙用</h3>
<p>很多人以为&nbsp;data-*&nbsp;只是给 JS 用的,其实 CSS 也能完美利用它。</p>
<p>场景一:通过属性选择器控制样式</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">/* 当 data-is-vip 为 "true" 时,背景变金 */
div {
background: gold;
border: 2px solid orange;
}</pre>
</div>
<p>场景二:利用&nbsp;attr()&nbsp;显示数据<br>这是一个非常酷的技巧,可以用来做 Tooltip 或者计数器显示。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">div::after {
/* 直接把 data-value 的值显示在页面上 */
content: "当前分值: " attr(data-value);
font-size: 12px;
color: #666;
}</pre>
</div>
<div>
<div>
<h2 data-id="heading-4">第二阶段:进阶——JavaScript 如何读写?</h2>
<p>这才是重头戏。在 JS 中操作&nbsp;data-*&nbsp;有两种方式:<strong>传统派</strong>&nbsp;和&nbsp;<strong>现代派</strong>。</p>
<h3 data-id="heading-5">1. 传统派:getAttribute&nbsp;/&nbsp;setAttribute</h3>
<p>这是最稳妥的方法,兼容性最好(虽然现在也没人要兼容 IE6 了)。</p>
</div>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">const el = document.getElementById('user-card');

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

// 修改
el.setAttribute('data-value', '100');</pre>
</div>
<div>
<div>
<p><strong>特点</strong>:读出来永远是<strong>字符串</strong>。哪怕你存的是&nbsp;100,取出来也是&nbsp;"100"。</p>
<h3 data-id="heading-6">2. 现代派:dataset&nbsp;API (推荐 ✨)</h3>
<p>HTML5 为每个元素提供了一个&nbsp;dataset&nbsp;对象(DOMStringMap),它将所有的&nbsp;data-*&nbsp;属性映射成了对象的属性。</p>
<p><strong>这里有个大坑(或者说是规范),请务必注意:</strong><br>
HTML 中的&nbsp;<strong>连字符命名 (kebab-case)</strong> &nbsp;会自动转换为 JS 中的&nbsp;<strong>小驼峰命名 (camelCase)</strong> 。</p>

</div>

</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">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 属性会被移除</pre>
</div>
<div>
<div>
<blockquote>
<p><strong>💡 敲黑板</strong>:dataset&nbsp;里的属性名<strong>不支持大写字母</strong>。如果你在 HTML 里写&nbsp;data-MyValue="1", 浏览器会强制转为小写&nbsp;data-myvalue,JS 里就得用&nbsp;dataset.myvalue&nbsp;访问。所以,HTML 里老老实实全小写吧。</p>
</blockquote>
<hr>
<h2 data-id="heading-7">第三阶段:深入——类型陷阱与性能权衡</h2>
<h3 data-id="heading-8">1. 一切皆字符串</h3>
<p>不管你赋给&nbsp;dataset&nbsp;什么类型的值,最终都会被转为字符串。</p>
</div>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">el.dataset.count = 100;      // HTML: data-count="100"
el.dataset.active = true;      // HTML: data-active="true"
el.dataset.config = {a: 1};    // HTML: data-config="" -&gt; 灾难!</pre>
</div>
<div>
<div>
<p><strong>避坑指南</strong>:</p>
<ul>
<li>如果你要存数字,取出来时记得&nbsp;Number(el.dataset.count)。</li>
<li>如果你要存布尔值,判断时不能简单用&nbsp;if (el.dataset.active),因为&nbsp;"false"&nbsp;字符串也是真值!要用&nbsp;el.dataset.active === 'true'。</li>
<li><strong>千万不要</strong>试图在&nbsp;data-*&nbsp;里存复杂的 JSON 对象。如果非要存,请使用&nbsp;JSON.stringify(),但在 DOM 上挂载大量字符串数据会影响性能。</li>
</ul>
<h3 data-id="heading-9">2. 性能考量</h3>
<ul>
<li><strong>读写速度</strong>:dataset&nbsp;的访问速度在现代浏览器中非常快,但在极高频操作下(比如每秒几千次),直接操作 JS 变量肯定比操作 DOM 快。</li>
<li><strong>重排与重绘</strong>:修改&nbsp;data-*&nbsp;属性会触发 DOM 变更。如果你的 CSS 依赖属性选择器(如&nbsp;div),修改属性可能会触发页面的重排(Reflow)或重绘(Repaint)。</li>
</ul>
<hr>
<h2 data-id="heading-10">第四阶段:实战——优雅的事件委托</h2>
<p>data-value&nbsp;最经典的用法之一就是在列表项的事件委托中。</p>
<p><strong>需求</strong>:点击列表中的“删除”按钮,删除对应项。</p>
</div>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;ul id="todo-list"&gt;
&lt;li&gt;
    &lt;span&gt;学习 HTML5&lt;/span&gt;
    &lt;!-- 把 ID 藏在这里 --&gt;
    &lt;button class="btn-delete" data-id="101" data-action="delete"&gt;删除&lt;/button&gt;
&lt;/li&gt;
&lt;li&gt;
    &lt;span&gt;写掘金文章&lt;/span&gt;
    &lt;button class="btn-delete" data-id="102" data-action="delete"&gt;删除&lt;/button&gt;
&lt;/li&gt;
&lt;/ul&gt;
</pre>
</div>
<p>  </p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">const list = document.getElementById('todo-list');

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

if (action === 'delete') {
    console.log(`准备删除 ID 为 ${id} 的条目`);
    // 这里发送请求或操作 DOM
    // deleteItem(id);
}
});</pre>
</div>
<div>
<div>
<p><strong>为什么这么做优雅?</strong><br>
你不需要给每个按钮都绑定事件,也不需要去分析 DOM 结构(比如&nbsp;e.target.parentNode...)来找数据。数据就在元素身上,唾手可得。</p>
<hr>
<h2 data-id="heading-11">总结与“禁忌”</h2>
<p>HTML5 的&nbsp;data-*&nbsp;属性是连接 DOM 和数据的一座轻量级桥梁。</p>
<p><strong>什么时候用?</strong></p>
<ul>
<li>当需要把少量数据绑定到特定 UI 元素上时。</li>
<li>当 CSS 需要根据数据状态改变样式时。</li>
<li>做事件委托需要传递参数时。</li>


</ul>
<p><strong>什么时候别用?(禁忌)</strong></p>
<ol>
<li><strong>不要存储敏感数据</strong>:用户可以直接在浏览器控制台修改 DOM,千万别把&nbsp;data-password&nbsp;或&nbsp;data-user-token&nbsp;放在这。</li>
<li><strong>不要当数据库用</strong>:别把几 KB 的 JSON 数据塞进去,那是 JS 变量或者是 IndexDB 该干的事。</li>
<li><strong>SEO 无用</strong>:搜索引擎爬虫通常不关心&nbsp;data-*&nbsp;里的内容,重要的文本内容还是要写在标签里。</li>


</ol><hr>
<p><strong>最后一句</strong>:<br>
代码整洁之道,始于不再乱用 Class。下次再想存个 ID,记得想起那个以&nbsp;data-&nbsp;开头的帅气属性。</p>

</div>
<div>
<h3 id="tid-D8HBxE">如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。</h3>
</div>
<p><em><img src="https://img2024.cnblogs.com/blog/2149129/202501/2149129-20250122165814748-630765389.png" alt="" loading="lazy"></em></p>
</div><br><br>
来源:https://www.cnblogs.com/smileZAZ/p/19633264
頁: [1]
查看完整版本: HTML5 自定义属性 data-*:别再把数据塞进 class 里了!