Мы хотим сделать этот проект с открытым исходным кодом доступным для людей во всем мире. Пожалуйста, помогите нам перевести это руководство на другие языки.

Элемент "template"

Встроенный элемент <template> предназначен для хранения шаблона HTML. Браузер полностью игнорирует его содержимое, проверяя лишь синтаксис, но мы можем использовать этот элемент в JavaScript, чтобы создать другие элементы.

В теории, для хранения разметки мы могли бы создать невидимый элемент в любом месте 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>).

Именно они и формируют теневой 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> не поддерживает итерацию, связывания данных или подстановки переменных. Однако эти возможности можно реализовать поверх него.

Карта учебника