使用資料屬性
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)