Веб-компонент (ваниль, без полимера): как загрузить <template> контент?

Я новичок в веб-компоненте. Я проверил некоторый пример, но я действительно не могу понять, как загрузить (вставить в DOM) содержимое отдельного веб-компонента. Начиная с этого примера, я поместил этот код в файл с именем my-element.html:

<template id="my-element">
  <p>Yes, it works!</p>
</template>
<script>
    document.registerElement('my-element', class extends HTMLElement {
      constructor() {
      super(); 
      let shadowRoot = this.attachShadow({mode: 'open'});
      const t = document.querySelector('#my-element');
      const instance = t.content.cloneNode(true);
      shadowRoot.appendChild(instance);
    }
});
</script>

Это мой index.html:

<!doctype html> 
<html>
 <head>
   <meta charset="utf-8">
   <title>my titile</title>
   <link rel="import" href="my-element.html">
</head>
<body>
  Does it work?
  <my-element></my-element>
</body>
</html>

Я на последней версии Chrome 56, поэтому мне не нужен polyfill. Я запускаю Polyserve, и только "Это работает?" появляется. Я попробовал (как и в оригинальном примере) синтаксис "customElements.define" вместо "document.registerElement", но не сработает. У тебя есть идеи? А что мне изменить, если я не хочу использовать теневой дом?

Спасибо

1 ответ

Решение

Это потому, что когда вы делаете:

document.querySelector( '#my-element' );

...document ссылается на основной документ index.html

Если вы хотите получить шаблон, вы должны использовать вместо document.currentScript.ownerDocument

var importedDoc = document.currentScript.ownerDocument;
customElements.define('my-element', class extends HTMLElement {
      constructor() {
          super(); 
          let shadowRoot = this.attachShadow({mode: 'open'});
          const t = importedDoc.querySelector('#my-element');
          const instance = t.content.cloneNode(true);
          shadowRoot.appendChild(instance);
    }
});

Обратите внимание, что document.currentScript является глобальной переменной, поэтому она ссылается на ваш импортированный документ только тогда, когда он анализируется в данный момент. Вот почему его значение сохраняется в переменной (здесь: importedDoc) для повторного использования позже (в constrcutor вызов)

Если у вас есть несколько импортированных документов, вы можете выделить их в закрытии (как описано в этом посте):

( function ( importedDoc )
{
    //register element
} )(document.currentScript.ownerDocument);
Другие вопросы по тегам