template - garevna/js-course GitHub Wiki

ico25 <template>


Элемент <template> предназначен для хранения шаблона разметки

warn-25 Он не отображается на странице

warn-25 Он парсится браузером, поэтому должен содержать только валидный код разметки


ico25 DocumentFragment

это фрагмент документа, у которого нет родителя в дереве DOM

DocumentFragment содержит DOM-элементы ( nodes ), как и объект document

Но поскольку фрагмент документа не является частью структуры DOM, он не отображается на странице

Это шаблон разметки, который при необходимости может быть вставлен в нужное время в нужном месте


cap-25 1

Откроем вкладку Elements инструментов разработчика и вставим в элемент body следующий код разметки:

<body>
    <template id="sample">
        <h3>Template header</h3>
        <p>Template text</p>
    </template>
</body>

При этом на странице ничего не появится, а вот во вкладке Elements мы увидим следующую картинку

<template id="sample">
  ▼ #document-fragment
     <h3>Template header</h3>
     <p>Template text</p>
  </template>

ico25 content

Свойство content элемента template содержит код разметки, находящийся в контейнере <template>...</template>

cap-25 2

Шаблон разметки
<template id="svg">
    <svg width="400" height="400">
        <circle cx="200" cy="200" 
                r="100" 
                fill="transparent"
                stroke="red" 
                style="stroke-width:5">
        </circle>
    </svg>
</template>

Выведем в консоль свойство content

content
const circle = document.querySelector ( "#svg" )
console.dir ( circle.content )
Результат
▼ #document-fragment
    baseURI: "about:blank"
    childElementCount: 2
  ► childNodes: NodeList(5) [text, h3, text, p, text]
  ► children: HTMLCollection(2) [h3, p]
  ► firstChild: text
  ► firstElementChild: h3
    isConnected: false
  ► lastChild: text
  ► lastElementChild: p
    nextSibling: null
    nodeName: "#document-fragment"
    nodeType: 11
    nodeValue: null
  ► ownerDocument: document
    parentElement: null
    parentNode: null
    previousSibling: null
    textContent: "↵        Template header↵        Template text↵    "
  ► __proto__: DocumentFragment

ico25 Вставка в DOM

Если выполнить код:

document.body.appendChild ( circle.content )

то после вставки в DOM содержимого шаблона контейнер <template id="svg"></template> будет пустым

Можно проверить это:

console.dir ( circle.content )

Свойство childNodes будет NodeList [ ] ( пустая коллекция узлов )

Свойство children будет HTMLCollection [ ] ( пустая коллекция элементов )

warn-25 Для многоразового использования шаблона разметки нужно использовать метод cloneNode ( true )
document.body.appendChild ( circle.content.cloneNode ( true ) )
warn-25 true указывает на глубокое копирование, т.е. всех подузлов дерева

cap-25 3

Шаблон разметки
<template id="sample">
    <style>
        svg { border: dotted 1px; }
        circle { stroke-width:5; }
    </style>
    <svg width="400" height="400" id="svg">
        <circle cx="200" cy="200" r="100" 
                id="circle"
                fill="transparent" 
                stroke="red">
        </circle>
    </svg>
</template>
Класс
class CanvasElement extends HTMLElement {
    constructor () {
        super()
        var shadow = this.attachShadow ( { mode: 'open' } )
        var sample = document.querySelector ( "#sample" )
        shadow.appendChild ( sample.content )
    }
}
customElements.define ( 'canvas-element', CanvasElement )
Вставка на страницу
<canvas-element></canvas-element>

cap-25 4

Теперь давайте все сделаем на чистом JS:

const template = document.body.appendChild (
    document.createElement ( "template" )
)

template.innerHTML = `
    <style>
        .red { color: red; }
        .div { width: 100px; height: 50px; border: solid 1px green; }
    </style>
    <div class="div"></div>
    <p class="red">Hello!</p>
`

customElements.define( 'sample-element',
  class extends HTMLElement {
    constructor() {
      super()
      const shadowRoot = this.attachShadow({ mode: 'open' })
        .appendChild( template.content.cloneNode(true) )
  }
})

Теперь вы можете сколько угодно раз вставить на страницу:

document.body.appendChild (
    document.createElement ( "sample-element" )
)

Жутко удобно, правда ? wink-25

⚠️ **GitHub.com Fallback** ⚠️