テンプレート

JS中にHTMLを文字列として埋め込むのではなく、<template>タグを使用する場合の例です。

ソースコード

とりあえずソースコードは次のようになります。
このソースコードで作るカスタムタグは最初のサンプルと同じです。

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>WebContent Sample</title>

	<template id="TmplTwoSlot">
		<div>
			<div>
				<slot></slot>
			</div>
			<div>
				<div class="inline-div">
					<slot name="inner1"></slot>
				</div>
				<div class="inline-div">
					<slot name="inner2"></slot>
				</div>
			</div>
		</div>
		<style>
		.inline-div {
			display: inline-block;
		}
		</style>
	</template>

	<script>
	class TwoSlot extends HTMLElement {
		constructor(){
			super();
		}

		connectedCallback(){
			let sr = this.attachShadow({mode: "open"});
			const tmpl = document.getElementById("TmplTwoSlot");
			const clone = document.importNode(tmpl.content, true);
			sr.appendChild(clone);
		}
	}

	customElements.define("two-slot", TwoSlot);
	</script>
</head>
<body>
	<two-slot id="TwoSlotSample">
		<p slot="inner1" class="left">hoge</p>
		<p slot="inner2" class="right">fuga</p>
		<div class="main">
			<h1>タイトル</h1>
			<div>
				これはメインのコンテンツです。
			</div>
		</div>
	</two-slot>
</body>
</html>

説明

<template>

最初のサンプルではTwoSlotクラスのtemplate()静的メソッドで作っていたHTMLを<template>に切り出した形になっています。

<template>タグの内容はページが読み込まれてもレンダリングされません。
MDNのドキュメントにも書いてありますが、JSを使用してインスタンス生成するためのテンプレート(コンテンツの断片)で、JSで動的生成しないなら意味のないタグです。

connectedCallback()

テンプレートを利用するために処理が変更になっています。

自身にattachShadow()するのは同じですが、テンプレート要素を取得し(36行目)、document.inportNode()でそれを複製して(37行目)、シャドウルートに追加しています。

つまり、シャドウルート以下に挿入する内容を<template>から取ってくる様に変更されたと言うわけです。

動作確認

当然、最初のサンプルと同じになります。

hoge

fuga

タイトル
これはメインのコンテンツです。

まとめ

WebComponentsを調べ始めて割と早い段階で<template>のことを読んでいました。と言うか、WebComponentsは少なくとも1回大きく変更されている様で、古いやり方(興味ある人はGoogle先生に聞いてみてください。Object.create()でHTMLElementを継承したオブジェクトを作成し、document.registerElement()で登録するやり方です。現在はこの方法は破棄されています)の記事がたくさん見つかるのですが、そこで<template>を使っていたのです。

その時に思ったのが、これはそんなに便利なのか?でした。
むしろ、最初のサンプルの様にすればJSに閉じるのでそっちの方が便利に思えたのです。テンプレート文字列を使えばHTMLはそのまま書けるし、変数埋め込みができる分そちらの方が便利に思えたわけです。
ですが、現在では<template>は非常に有効な機能だと思っています。その理由はその次で説明します。