Вбудований елемент <template>
використовується як обгортка для шаблонної розмітки HTML. Браузер не бере до уваги його вміст, лише перевіряє на правильність синтаксису. Ми можемо доступитися та використовувати його у JavaScript, щоб створювати інші елементи.
Теоретично, ми могли б створити будь-який невидимий елемент де-небудь у HTML для зберігання у ньому розмітки HTML. Тоді що ж такого особливого у <template>
?
По-перше, він може містити у собі будь-який коректний HTML, навіть якщо за звичайних умов він би потребував якогось додаткового тега.
Наприклад, ми можемо помістити тег рядка таблиці <tr>
:
<
template
>
<
tr
>
<
td
>
Вміст</
td
>
</
tr
>
</
template
>
Зазвичай, якщо ми пробуємо помістити тег <tr>
всередину, скажімо, тега <div>
, браузер помічає некоректну структуру DOM та “виправляє” її, додаючи навколо <table>
. Але це не те, що ми хочемо. На противагу цьому, <template>
зберігає дані у тому вигляді, у якому ми їх туди помістили.
Ми також можемо помістити всередину <template>
стилі чи скрипт:
<
template
>
<
style
>
p
{
font-weight
:
bold;
}
</
style
>
<
script
>
alert
(
"Привіт"
)
;
</
script
>
</
template
>
Браузер розглядає вміст тега <template>
як такий, який існує “за межами документа”: до нього не застосовуються стилі, не виконуються скрипти, <video autoplay>
не запускається і тому подібне.
Вміст починає опрацьовуватися (застосовуються стилі, виконуються скрипти і т. ін.), коли ми вставляємо його у документ.
Вставка шаблону
Вміст template доступний у його властивості content
як DocumentFragment – спеціальний тип вузла DOM.
Ми можемо працювати з ним як зі всіма іншими вузлами DOM, за винятком однієї особливості: коли ми його кудись вставляємо, вставляються його дочірні елементи, а не він сам.
Наприклад:
<
template
id
=
"
tmpl"
>
<
script
>
alert
(
"Привіт"
)
;
</
script
>
<
div
class
=
"
message"
>
Привіт, світ!</
div
>
</
template
>
<
script
>
let
elem =
document.
createElement
(
'div'
)
;
// Клонувати вміст шаблону, для його подальшого використання
elem.
append
(
tmpl.
content.
cloneNode
(
true
)
)
;
document.
body.
append
(
elem)
;
// Тепер запускається скрипт з <template>
</
script
>
Перепишемо приклад Shadow DOM з попереднього розділу, використовуючи <template>
:
<
template
id
=
"
tmpl"
>
<
style
>
p
{
font-weight
:
bold;
}
</
style
>
<
p
id
=
"
message"
>
</
p
>
</
template
>
<
div
id
=
"
elem"
>
Клікни мене</
div
>
<
script
>
elem.
onclick
=
function
(
)
{
elem.
attachShadow
(
{
mode
:
'open'
}
)
;
elem.
shadowRoot.
append
(
tmpl.
content.
cloneNode
(
true
)
)
;
// (*)
elem.
shadowRoot.
getElementById
(
'message'
)
.
innerHTML =
"Привіт зі світу тіней!"
;
}
;
</
script
>
У рядку (*)
, коли ми клонуємо та вставляємо tmpl.content
, як його DocumentFragment
, натомість отримуємо його дочірні (<style>
, <p>
).
Вони формують Shadow DOM:
<
div
id
=
"
elem"
>
#shadow-root
<
style
>
p
{
font-weight
:
bold;
}
</
style
>
<
p
id
=
"
message"
>
</
p
>
</
div
>
Підсумки
Узагальнимо:
<template>
його вмістом може бути будь-який синтаксично правильний HTML.<template>
вміст вважається “за межами документа”, тому він ні на що не впливає.- Ми можемо доступитися до
template.content
з JavaScript, клонувати його, щоб потім знову використати у новому компоненті.
Тег <template>
є унікальним, оскільки:
- Браузер перевіряє HTML синтаксис всередині нього (на відміну від рядка всередині скрипта з тією ж розміткою).
- …Але все одно дозволяє використання будь-якого тега HTML, навіть тих, використання яких не має сенсу без відповідної обгортки (напр.
<tr>
). - Вміст стає інтерактивним: виконуються скрипти, запускається
<video autoplay>
і т. ін., коли ми переміщаємо його у документ.
Елемент <template>
не має жодних механізмів ітерації, зв’язування даних чи заміни змінних, але ми можемо реалізувати їх поверх нього.
Коментарі
<code>
, для кількох рядків – обгорніть їх тегом<pre>
, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)