使用数据属性
HTML 在设计时就考虑了可扩展性,用于存储应与特定元素关联但无需具有任何已定义含义的数据。data-*
属性允许我们在标准的、语义化的 HTML 元素上存储额外信息,而无需使用其他技巧,例如非标准属性或 DOM 上的额外属性。
HTML 语法
语法很简单。任何元素上以 data-
开头的属性都是 data 属性。假设您有一些文章,并且想存储一些没有视觉表示的额外信息。只需为此使用 data
属性即可。
<main>
<article
id="electric-cars"
data-columns="3"
data-index-number="12314"
data-parent="cars">
<!-- Electric car content -->
</article>
<article
id="solar-cars"
data-columns="3"
data-index-number="12315"
data-parent="cars">
<!-- Solar car content -->
</article>
<article
id="flying-cars"
data-columns="4"
data-index-number="12316"
data-parent="cars">
<!-- Flying car content -->
</article>
</main>
JavaScript 访问
在 JavaScript 中读取这些属性的值也很简单。您可以使用带有完整 HTML 名称的 getAttribute()
来读取它们,但标准定义了一种更简单的方法:一个可以通过 dataset
属性读取的 DOMStringMap
。
要通过 dataset
对象获取 data
属性,请按属性名称中 data-
后面的部分获取属性(请注意,破折号会被转换为 驼峰式命名)。
const article = document.querySelector("#electric-cars");
// The following would also work:
// const article = document.getElementById("electric-cars")
article.dataset.columns; // "3"
article.dataset.indexNumber; // "12314"
article.dataset.parent; // "cars"
每个属性都是一个字符串,可以读取和写入。在上面的例子中,设置 article.dataset.columns = 5
会将该属性更改为 "5"
。
您还可以使用 document.querySelector()
或 document.querySelectorAll()
配合 data 属性选择器来查找一个或所有匹配的元素。
// Find all elements with a data-columns attribute
const articles = document.querySelectorAll("[data-columns]");
// Find all elements with data-columns="3"
const threeColumnArticles = document.querySelectorAll('[data-columns="3"]');
// You can then iterate over the results
threeColumnArticles.forEach((article) => {
console.log(article.dataset.indexNumber);
});
CSS 访问
请注意,由于 data 属性是纯 HTML 属性,您甚至可以从 CSS 中访问它们。例如,要在文章上显示父级数据,您可以使用 CSS 中的 生成的内容 和 attr()
函数。
article::before {
content: attr(data-parent);
}
您还可以使用 CSS 中的 属性选择器 根据数据更改样式。
article[data-columns="3"] {
width: 400px;
}
article[data-columns="4"] {
width: 600px;
}
数据值是字符串。数字值在选择器中必须用引号括起来,样式才会生效。
示例
样式变体
假设您有一个 callout
类。现在您想实现不同的变体,例如“note”和“warning”。传统上,人们会使用不同的类名。
<div class="callout callout--note">...</div>
<div class="callout callout--warning">...</div>
.callout {
margin: 0.5em 0;
padding: 0.5em;
border-radius: 4px;
border-width: 2px;
border-style: solid;
}
.callout--note {
border-color: rgb(15 15 235);
background-color: rgb(15 15 235 / 0.2);
}
.callout--warning {
border-color: rgb(235 15 15);
background-color: rgb(235 15 15 / 0.2);
}
使用 data 属性,您可以考虑以下替代方案:
<div class="callout">...</div>
<div class="callout" data-variant="note">...</div>
<div class="callout" data-variant="warning">...</div>
.callout {
margin: 0.5em 0;
padding: 0.5em;
border-radius: 4px;
border-width: 2px;
border-style: solid;
}
/* Default style */
.callout:not([data-variant]) {
border-color: rgb(15 15 15);
background-color: rgb(15 15 15 / 0.2);
}
.callout[data-variant="note"] {
border-color: rgb(15 15 235);
background-color: rgb(15 15 235 / 0.2);
}
.callout[data-variant="warning"] {
border-color: rgb(235 15 15);
background-color: rgb(235 15 15 / 0.2);
}
这有多种好处:
- 它消除了许多无效状态,例如应用
callout--note
而不添加callout
,或同时应用多个变体。 - 单独的
data-variant
属性允许通过 linting 或类型检查对有效值进行静态分析。 - 切换变体更直观:您可以使用
div.dataset.variant = "warning";
来代替操作classList
,这需要多个步骤。
将任意数据与 DOM 元素关联
许多 Web 应用程序以 JavaScript 数据作为其 UI 状态的真相来源。在这些情况下,您只需添加渲染所需的 HTML 属性。当所有内容都存在于标记中,而 JavaScript 只用于处理事件、同步状态等情况时,data 属性非常有用。
例如,在我们 带滚动边距的轮播图 示例中,我们有一个已经填充了许多 <img>
元素的 HTML 页面。图片的源最初存储在 data-src
中,以防止任何请求被触发,而真实的 src
仅在 <img>
进入视图时添加。数据(图片源)与元素同处一地,JavaScript 只负责定义行为。
问题
请勿将应可见和可访问的内容存储在 data 属性中,因为辅助技术可能无法访问它们。此外,搜索引擎爬虫可能不会索引 data 属性的值。通常,如果您只打算显示 data 属性,可以直接修改 textContent
。
另见
- 本文改编自 hacks.mozilla.org 上的 在 JavaScript 和 CSS 中使用 data 属性。
- SVG 2 也支持自定义属性;请参阅
HTMLElement.dataset
和data-*
以获取更多信息。 - 如何使用 HTML data 属性 (Sitepoint)