MDNでtemplateとslotの使い方について学ぶ


ゴール

MDNを見ながらtemplateとslotについて知ったつもりになる。

参考

template と slot の使い方 - Web Components | MDN

The truth about templates

書いてあるサンプルのHTMLのみ書いてブラウザで表示してみる。

<template id="my-paragraph">
  <p>My paragraph</p>
</template>

おー!表示されない(`・ω・´)
Javascriptを読み込んで.jsに以下を記述。

let template = document.getElementById('my-paragraph');
let templateContent = template.content;
document.body.appendChild(templateContent);

おー!表示された(`・ω・´)
見えないtemplateを用意しておいて、動的に生成できるって感じですかね。

Using templates with web components

.js.htmlを以下のように書き換えて実行。

// javascript
customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById('my-paragraph');
      let templateContent = template.content;
      const shadowRoot = this.attachShadow({mode: 'open'})
      .appendChild(templateContent.cloneNode(true));
    }
  }
);
// html
<template id="my-paragraph">
  <style>
    p {
        color: white;
        background-color: #666;
        padding: 5px;
    }
  </style>
  <p>My paragraph</p>
</template>
<my-paragraph></my-paragraph>

おぉ〜...?ってことで1つずつ見ていきます。

HTMLの方はtemplateが用意されているだけですね。.jsの読み込みをしなければ画面上、何も表示されません(my-paragraphタグは表示されます)。

続いて.jsの方を見ていきます。
customElements.defineでカスタムタグを作成は問題無しですね。HTMLElementを継承したクラスを引数に与えているのもOK。id="my-paragraph"のcontentをtemplateContent変数に入れてるのもOK。
cloneNodeをしてるのは複製しないと2度以上使えないから。とは言え動かした結果から言ってるので何でcloneNodeが必要なのかは理解できてない

Adding flexibility with slots

ここまでのサンプルでは高々1種類のテキストを表示できるのみで、普通の paragraph よりも使えません。

お、おう。

slot はその name 属性で区別されており、template の中で任意のマークアップで slot の内容のデフォルト値を埋めることができます。

...なるほど、わからん
ということで何となくの雰囲気で試してみる。

// html
<template id="my-paragraph">
  <slot></slot>
  <slot name="hoge"></slot>
</template>
<my-paragraph>
  <p>name無しのslotに追加される</p>
  <p>ここもname無しのslot要素に追加される</p>
  <p slot="hoge">name="hoge"に追加される</p>
  <p slot="piyo">name="piyo"に追加される(piyoが無いので追加されない)</p>
</my-paragraph>
// javascript
customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById('my-paragraph');
      let templateContent = template.content;
      const shadowRoot = this.attachShadow({
          mode: 'open'
      })
      .appendChild(templateContent.cloneNode(true));
    }
  }
);

こういう理解であってるんだろうか...

おわり

何となくわかった気にはなれた。気がする。
Vue.js触ってみようかな。