Использование шаблонов может помочь разделить на модули и повторно использовать HTML-код на веб-сайте. Определяя шаблоны, инкапсулирующие часто используемый HTML-контент, мы можем уменьшить дублирование кода и упростить его обновление. Шаблон обычно используется вместе с пользовательскими элементами. Когда вы создаете пользовательский элемент с теневым DOM, теневой DOM создается динамически и существует как инкапсулированное дерево DOM внутри пользовательского элемента.
Тень ДОМ
Shadow DOM — это еще одна длинная история, я не буду вдаваться в подробности, вы можете обратиться к MDN Web Docs
«Теневой DOM позволяет присоединять скрытые деревья DOM к элементам в обычном дереве DOM — это дерево теневой DOM начинается с теневого корня, под которым вы можете прикрепить любой элемент так же, как и обычный DOM».
«Вы можете прикрепить теневой корень к любому элементу, используя метод Element.attachShadow(). В качестве параметра принимает объект параметров, который содержит один параметр — режим — со значением «открыто» или «закрыто».
Использование шаблона
Во-первых, давайте использовать шаблон для отображения в определенном формате.
Например, у нас может быть список изображений, полученных из API, которые мы хотим отобразить в определенном формате, мы можем определить шаблон и использовать JavaScript для заполнения шаблона данными и добавления его в DOM.
Мы получаем 10 случайных изображений из API с помощью запроса на выборку. Для каждого элемента в ответе мы клонируем item-template и устанавливаем src, textContent и добавляем экземпляр клонированного шаблона в контейнер.
<template id="item-template"> <div class="item"> <img src="" alt="Item image"> <h2></h2> <p></p> </div> </template> const catTemplate = document.getElementById('item-template'); const catContainer = document.getElementById('container'); const apiKey = 'live_g2TlRXkZBAczbt1TkDyGIjgWk2Yd1wHzR7NahHoqdHGLa0bVho0uKmSl8u9otL1v'; fetch(`https://api.thecatapi.com/v1/images/search?limit=10`, { headers: { 'x-api-key': apiKey } }) .then(response => response.json()) .then(data => { data.forEach(cat => { const catInstance = catTemplate.content.cloneNode(true); catInstance.querySelector('img').src = cat.url; catInstance.querySelector('h2').textContent = cat.id; catInstance.querySelector('p').textContent = `Width: ${cat.width} Height: ${cat.height}`; catContainer.appendChild(catInstance); }); }) .catch(error => { console.error('Error fetching cat images:', error); });
Вложенный шаблон
Теперь мы заполнили контейнер 10 изображениями кошек, затем мы хотим добавить некоторые интерактивные функции к каждому изображению. Мы хотим добавить две кнопки на каждую картинку. Мы можем создать еще один шаблон и вложить его в шаблон элемента.
<template id="item-template"> <div class="item"> <img src="" alt="Item image"> <h2></h2> <p></p> <button-group></button-group> </div> </template> <template id="button-template"> <button class="share-btn">Share</button> <button class="favorite-btn">Favorite</button> </template>
Использование шаблона с пользовательскими элементами
Шаблон и пользовательские элементы обычно появляются вместе.
Без определения пользовательского элемента (который здесь получен из шаблона с помощью document.getElementById(‘id-name’).content), шаблон не будет отображаться.
В этом примере мы определяем пользовательский элемент с именем button-group, который инкапсулирует шаблон кнопки. Затем мы добавляем элемент button-group в item-template, как указано выше, и используем его в цикле, который заполняет контейнер с элементами из API.
class ButtonGroup extends HTMLElement { constructor() { super(); const template = document.getElementById('button-template'); const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.appendChild(template.content.cloneNode(true)); shadowRoot.querySelector('.share-btn').addEventListener('click', () => { console.log('Share button clicked'); }); shadowRoot.querySelector('.favorite-btn').addEventListener('click', () => { console.log('Favorite button clicked'); }); } } customElements.define('button-group', ButtonGroup);
Использование шаблона с пользовательским элементом и слотом
Как мы упоминали выше, шаблон используется для определения структуры и стиля пользовательского элемента, но вы можете настроить содержимое пользовательского элемента без изменения самого шаблона. Вот здесь и пригодится элемент slot. Он служит заполнителем в шаблоне, позволяя передавать содержимое из основного документа в пользовательский элемент, эффективно корректируя данные в клонированном шаблоне.
<template id="button-template"> <button class="share-btn">Share</button> <button class="favorite-btn">Favorite</button> <slot name="cat"> <legend>meow!</legend> </slot> </template>
В этом примере мы добавляем слот в button-template, после чего на картинке будет отображаться «мяу!»
Однако мы могли отредактировать «мяу!» без изменения шаблона кнопки, вместо этого мы могли бы изменить содержимое, которое имеет слот с тем же атрибутом имени, здесь он находится в шаблоне элемента, и мы меняем его на «мяу-мяу», тогда на картинке будет «мяу-мяу».
<template id="item-template"> <div class="item"> <img src="" alt="Item image"> <h2></h2> <p></p> <button-group> <p slot="cat">meow meow</p> </button-group> </div> </template>
Ссылка:
Сеть разработчиков Mozilla. (н.д.). Использование теневого DOM. Веб-документы MDN. https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM
веб.дев. (н.д.). Шаблон, слот и тень. веб.дев. https://web.dev/learn/html/template/
Репо работы:
https://github.com/Blurmilk/579-презентация