<template>: 內容模板元素
基線 廣泛可用
此功能已建立良好,並在許多裝置和瀏覽器版本上都能正常工作。它自 2015 年 11 月.
屬性
此元素包含 全域性屬性。
shadowrootmode-
為父元素建立 影子根。它是
Element.attachShadow()方法的宣告式版本,並接受相同的 列舉 值。注意:HTML 解析器在 DOM 中為第一個
<template>建立一個ShadowRoot物件,該物件具有設定為允許值的屬性。如果屬性未設定或未設定為允許值 - 或者如果在同一個父節點中已宣告式建立了ShadowRoot,則將構建一個HTMLTemplateElement。解析後,HTMLTemplateElement無法隨後更改為影子根,例如,透過設定HTMLTemplateElement.shadowRootMode。注意:你可能會在舊的教程和示例中找到非標準的
shadowroot屬性,這些屬性過去曾在 Chrome 90-110 中得到支援。此屬性已被刪除,並由標準shadowrootmode屬性取代。 shadowrootclonable-
將使用此元素建立的
ShadowRoot的clonable屬性值設定為true。如果設定,則使用Node.cloneNode()或Document.importNode()建立的影子主機(此<template>的父元素)的克隆將包含副本中的影子根。 shadowrootdelegatesfocus-
將使用此元素建立的
ShadowRoot的delegatesFocus屬性值設定為true。如果設定了此值,並且選擇了影子樹中的不可聚焦元素,則焦點將委託給樹中的第一個可聚焦元素。預設值為false。 shadowrootserializable實驗性-
將使用此元素建立的
ShadowRoot的serializable屬性值設定為true。如果設定,則可以透過呼叫Element.getHTML()或ShadowRoot.getHTML()方法(將options.serializableShadowRoots引數設定為true)序列化影子根。預設值為false。
使用說明
使用 <template> 元素主要有兩種方法。
模板文件片段
預設情況下,元素的內容不會被渲染。相應的 HTMLTemplateElement 介面包含一個標準的 content 屬性(沒有等效的 content/markup 屬性)。此 content 屬性是隻讀的,它儲存一個 DocumentFragment,該片段包含由模板表示的 DOM 子樹。此片段可以透過 cloneNode 方法克隆,並插入到 DOM 中。
使用 content 屬性時要小心,因為返回的 DocumentFragment 可能表現出意外的行為。有關更多詳細資訊,請參見下面的 避免 DocumentFragment 陷阱 部分。
宣告式影子 DOM
如果 <template> 元素包含 shadowrootmode 屬性,
如果元素的shadowrootmode屬性具有任何其他值,或者沒有shadowrootmode屬性,解析器會生成一個HTMLTemplateElement。類似地,如果存在多個宣告式影子根,則只有第一個被替換為ShadowRoot - 後續例項被解析為HTMLTemplateElement物件。
示例
生成表格行
首先,我們從示例的 HTML 部分開始。
<table id="producttable">
<thead>
<tr>
<td>UPC_Code</td>
<td>Product_Name</td>
</tr>
</thead>
<tbody>
<!-- existing data could optionally be included here -->
</tbody>
</table>
<template id="productrow">
<tr>
<td class="record"></td>
<td></td>
</tr>
</template>
首先,我們有一個表格,我們將在稍後使用 JavaScript 程式碼將內容插入到其中。然後是模板,它描述了一個表示單個表格行的 HTML 片段的結構。
現在表格已經建立並且模板已定義,我們使用 JavaScript 將行插入到表格中,其中每行都是使用模板作為其基礎構建的。
// Test to see if the browser supports the HTML template element by checking
// for the presence of the template element's content attribute.
if ("content" in document.createElement("template")) {
// Instantiate the table with the existing HTML tbody
// and the row with the template
const tbody = document.querySelector("tbody");
const template = document.querySelector("#productrow");
// Clone the new row and insert it into the table
const clone = template.content.cloneNode(true);
let td = clone.querySelectorAll("td");
td[0].textContent = "1235646565";
td[1].textContent = "Stuff";
tbody.appendChild(clone);
// Clone the new row and insert it into the table
const clone2 = template.content.cloneNode(true);
td = clone2.querySelectorAll("td");
td[0].textContent = "0384928528";
td[1].textContent = "Acme Kidney Beans 2";
tbody.appendChild(clone2);
} else {
// Find another way to add the rows to the table because
// the HTML template element is not supported.
}
結果是原始 HTML 表格,透過 JavaScript 向其追加了兩行。
實現宣告式影子 DOM
在本例中,在標記的開頭包含了一個隱藏的支援警告。如果瀏覽器不支援shadowrootmode屬性,則該警告將在稍後透過 JavaScript 設定為顯示。接下來,有兩個<article>元素,每個元素都包含巢狀的<style>元素,它們的行為不同。第一個<style>元素對整個文件是全域性的。第二個元素被限定在<template>元素所在位置生成的影子根中,因為存在shadowrootmode屬性。
<p hidden>
⛔ Your browser doesn't support <code>shadowrootmode</code> attribute yet.
</p>
<article>
<style>
p {
padding: 8px;
background-color: wheat;
}
</style>
<p>I'm in the DOM.</p>
</article>
<article>
<template shadowrootmode="open">
<style>
p {
padding: 8px;
background-color: plum;
}
</style>
<p>I'm in the shadow DOM.</p>
</template>
</article>
const isShadowRootModeSupported =
HTMLTemplateElement.prototype.hasOwnProperty("shadowRootMode");
document
.querySelector("p[hidden]")
.toggleAttribute("hidden", isShadowRootModeSupported);
具有委託焦點的宣告式影子 DOM
此示例演示瞭如何將shadowrootdelegatesfocus應用於宣告式建立的影子根,以及這種操作對焦點的影響。
程式碼首先使用帶有shadowrootmode屬性的<template>元素,在<div>元素內宣告一個影子根。這將顯示一個不可聚焦的包含文字的<div>元素和一個可聚焦的<input>元素。它還使用 CSS 來設定具有:focus的元素的樣式為藍色,並設定宿主元素的常規樣式。
<div>
<template shadowrootmode="open">
<style>
:host {
display: block;
border: 1px dotted black;
padding: 10px;
margin: 10px;
}
:focus {
outline: 2px solid blue;
}
</style>
<div>Clickable Shadow DOM text</div>
<input type="text" placeholder="Input inside Shadow DOM" />
</template>
</div>
第二個程式碼塊與之相同,除了它設定了shadowrootdelegatesfocus屬性,該屬性會將焦點委託給樹中的第一個可聚焦元素,如果樹中選擇了不可聚焦元素。
<div>
<template shadowrootmode="open" shadowrootdelegatesfocus>
<style>
:host {
display: block;
border: 1px dotted black;
padding: 10px;
margin: 10px;
}
:focus {
outline: 2px solid blue;
}
</style>
<div>Clickable Shadow DOM text</div>
<input type="text" placeholder="Input inside Shadow DOM" />
</template>
</div>
最後,我們使用以下 CSS 為父<div>元素應用綠色-黃色的邊框,當它獲得焦點時。
div:focus {
border: 2px solid red;
}
結果如下所示。當 HTML 首次渲染時,元素沒有樣式,如第一張圖片所示。對於沒有設定shadowrootdelegatesfocus的影子根,您可以點選除<input>以外的任何地方,焦點都不會改變(如果選擇<input>元素,它看起來就像第二張圖片)。
對於設定了shadowrootdelegatesfocus的影子根,點選文字(不可聚焦)會選擇<input>元素,因為它是樹中的第一個可聚焦元素。這也使父元素獲得焦點,如下所示。
避免 DocumentFragment 陷阱
當傳遞DocumentFragment值時,Node.appendChild和類似方法僅將該值的子節點移動到目標節點。因此,通常最好將事件處理程式附加到DocumentFragment的子節點,而不是附加到DocumentFragment本身。
考慮以下 HTML 和 JavaScript
HTML
<div id="container"></div>
<template id="template">
<div>Click me</div>
</template>
JavaScript
const container = document.getElementById("container");
const template = document.getElementById("template");
function clickHandler(event) {
event.target.append(" — Clicked this div");
}
const firstClone = template.content.cloneNode(true);
firstClone.addEventListener("click", clickHandler);
container.appendChild(firstClone);
const secondClone = template.content.cloneNode(true);
secondClone.children[0].addEventListener("click", clickHandler);
container.appendChild(secondClone);
結果
由於firstClone是一個DocumentFragment,因此呼叫appendChild時,只有它的子節點會被新增到container中;firstClone的事件處理程式不會被複制。相反,由於事件處理程式被新增到secondClone的第一個子節點,因此呼叫appendChild時事件處理程式會被複制,點選它會像預期的那樣工作。
技術摘要
規範
| 規範 |
|---|
| HTML 標準 # the-template-element |
瀏覽器相容性
BCD 表格僅在瀏覽器中載入
另請參見
part和exportpartsHTML 屬性<slot>HTML 元素:host,:host()和:host-context()CSS 偽類::part和::slottedCSS 偽元素ShadowRoot介面- 使用模板和插槽
- CSS 限定範圍 模組
- 宣告式影子 DOM(使用 html) 在使用影子 DOM中
- 宣告式影子 DOM 在 web.dev 上(2023 年)