Я только начал узнавать о пользовательских элементах HTML, и, прочитав серию вступлений, учебных пособий и документации, я думаю, что хорошо разбираюсь в том, как это работает, но у меня есть философский вопрос о том, как правильно использовать или не использовать {amp}lt;template{amp}gt; .

Пользовательские элементы дают вам возможность инкапсулировать новые функциональные возможности, упрощая структуру вашего HTML-документа и позволяя вам просто вставить {amp}lt;my-custom-element{amp}gt;...{amp}lt;/my-custom-element{amp}gt; вместо {amp}lt;div class="my-custom-element"{amp}gt;{amp}lt;span class="part1"{amp}gt;...{amp}lt;/span{amp}gt;{amp}lt;span class="part2"{amp}gt;...{amp}lt;/span{amp}gt;{amp}lt;/div{amp}gt; .

Определение класса для элемента затем устанавливает структуру и функциональность этого элемента. Затем в куче руководств описывается, как использовать {amp}lt;template{amp}gt;...{amp}lt;/template{amp}gt; и {amp}lt;slot{amp}gt;...{amp}lt;/slot{amp}gt; для настройки содержимого пользовательского элемента. Затем вам нужно будет включить код шаблона в каждый HTML-документ, в котором вы хотите использовать элемент, а не настраивать его в конструкторе класса пользовательского элемента. Разве это не противоречит тому факту, что пользовательские элементы помогают упростить и инкапсулировать функциональность таким образом, чтобы сделать их более переносимыми? Или я неправильно понимаю правильное использование и / или размещение шаблона в документе?

Просматривая SO, я могу найти следующий ответ на этот вопрос:

Как штамповать шаблон в автономных пользовательских элементах с помощью vanilla js?

Но ответ, по сути, обходит это все вместе и говорит: «Не используйте {amp}lt;template{amp}gt; », и поэтому не совсем проясняет мою путаницу.

Фактически элементы {amp}lt;template{amp}gt; могут быть импортированы из другого документа с помощью импорта HTML вместе с кодом Javascript, который определит пользовательский элемент:

 {amp}lt;link rel="import" src="my-custom-element.html"{amp}gt; ... {amp}lt;custom-element{amp}gt;{amp}lt;/custom-element{amp}gt; 

Поэтому его не нужно включать в каждый HTML-документ. Этот пост показывает минимальный пример.

Импорт HTML реализован только в Chrome и Opera. Если вы хотите использовать их вместе с Firefox и Safari, вам нужно использовать полифилл HTML Imports .

С другой стороны, на данный момент Mozilla и Apple не намерены реализовывать HTML-импорт непосредственно в своих браузерах. Поэтому они рекомендуют определять пользовательские элементы с чистыми модулями Javascript (с помощью import или {amp}lt;script src="..."{amp}gt; ) и вместо этого продвигать строки литералов шаблона , которые предлагают некоторые преимущества (переменные, функции), но иногда более сложны для код в IDE (из-за их строкового представления).

Возможно, в будущем стандартные HTML-модули будут приняты всеми браузерами, и {amp}lt;template{amp}gt; вернется в центр внимания …

Обратите внимание, что без HTML-импорта вы можете импортировать некоторые HTML-документы с помощью fetch() :

 fetch( "template.html" ) .then( stream ={amp}gt; stream.text() ) .then( text ={amp}gt; customElements.define( "ce", class extends HTMLElement { constructor() { super() this.attachShadow( { mode: 'open'} ) .innerHTML = text } } ) ) 

Обновление 2019

HTML-импорт не будет изначально поддерживаться после Chrome 73 . Затем вы должны использовать другие решения, перечисленные выше (polyfill, загрузчик альтернативных модулей, import JS или прямая загрузка с fetch ).

Отказ от ответственности: я являюсь автором библиотеки rich-component, упомянутой ниже.

После некоторого времени экспериментирования с пользовательскими элементами и недавнего создания полноценного проекта, основанного исключительно на них, я хотел бы поделиться своим пониманием этого:

  • любой компонент, крошечный, как это, является кандидатом, чтобы вырасти до некоторого зверя
  • HTML часть этого может вырасти до такой степени, что очень неудобно держать ее в JS
  • использовать шаблон, созданный и проанализированный один раз, и с этой точки клонировать и внедрить в теневой корень — это та же самая лучшая практика, что и использовать фрагмент документа вместо изменения живого DOM
  • если содержимое шаблона должно быть изменено от экземпляра компонента к экземпляру — может быть использована какая-то структура привязки данных, и если будет применен минималистский подход к ним — все еще может быть проще и эффективнее работать с документом клонированного из шаблона фрагмент, который оперирует строковыми или шаблонными литералами

Чтобы не писать снова и снова одни и те же десятки строк, я подготовил библиотеку rich-component , которая:

  • нормализует некоторый API для предоставления шаблона и всех этих «клонированных шаблонов, создающих тени, вставляющих содержимое шаблона в него» строк повторяющегося кода
  • известно, что он извлекает содержимое html, если указан html URL
  • кэширует шаблоны, поэтому выборка выполняется только один раз