Web Components とは何か
簡単に言ってしまえば、オリジナルタグを作れるHTMLの仕様です。
このあたりの記事が詳しいです。
https://html5experts.jp/shumpei-shiraishi/24239/
良い感じに小さくまとまっている実装が無かったので自作してみました。
Hello, Worldタグを作る
こんな感じになります。
https://iwtn.github.io/hello_world_tag/
後述しますが、ブラウザのサポート状況は微妙でChromeでしか表示できないと思います。
ソースコードはこちら
https://github.com/iwtn/hello_world_tag
Developer Tools で見ると、オリジナルのタグで出来ていることがわかりやすいと思います。
3つの基本要素(本当は4つ)と基本的な作り方
- template タグを使って構造を定義する
- HTMLElement を継承したクラスとして CustomElements を定義する
- 1で作った template を Shadow DOM として、2で作った CustomElements に組み込む
- (番外)HTML imports で他のページに読み込む(今回はやっていない)
(番外)HTML imports
せっかく作ったオリジナルタグなので、再利用のために他のページでも使いたいところです。
そのための仕様として HTML imports があります。
しかし、仕様が微妙なようで実装が進んでいないそうです。
代替案としては、最初に上げたURLの記事にある通り ES modules を使って再利用できます。
templateタグ
<template id="hello">
<style>
.colored {
color: red;
}
</style>
<div class="colored">
Hello, <span><content></content></span>!
</div>
</template>
このタグを書いただけではレンダリングされず、body, head, frameset のどこでも書けます。
HTMLのタグやCSSのスタイルを自由に記述できます。
<content></content>
の部分に作成したタグでくくった内容が入ります。
Custom Elements
class HelloDiv extends HTMLElement {
constructor() {
super();
// ShadowDOMを使った実装が入る
}
}
customElements.define('hello-tag', HelloDiv);
HTMLElement を継承して新しいタグを表すクラスを定義しています。
HTMLElementには、タグとしての基本的な属性を設定できたり、イベントを登録したりできるので、これを継承することで、様々な機能を持ったタグを作成できます。
Shadow DOM
const template = document.querySelector('#hello');
const node = document.importNode(template.content, true);
this.createShadowRoot();
this.shadowRoot.appendChild(node);
- template タグをDOM全体から取得し、そのコピーを作成しています。
- HTMLElement を継承したオリジナルタグに Shadow Root を用意して、そこに template で定義したDOMを入れます。
サンプルコードの中により上部で全体のスタイルを定義した style タグ(背景色と文字色をCSSで設定している)がありますが、オリジナルのタグはその影響も受けません。
これは Shadow DOM でカプセル化されているためです。
まとめと感想
これでオリジナルのタグを作るための土台はできたと思います。
この仕様が実際に使われるかはわかりませんが、フロントエンドがコンポーネント指向に向かっている現状では、押さえておいて悪くはないと思っています。
サポート状況
Chromeなら見れますが、実装が進んでいるとはとても言えない状況です。
- https://caniuse.com/#feat=template
- https://caniuse.com/#feat=shadowdomv1
- https://caniuse.com/#feat=custom-elementsv1
- https://caniuse.com/#feat=imports
参考URL
- template タグ
- https://www.html5rocks.com/ja/tutorials/webcomponents/template/
- Custom Elements
- https://www.html5rocks.com/ja/tutorials/webcomponents/customelements/
- Shadow DOM
- https://www.html5rocks.com/ja/tutorials/webcomponents/shadowdom/
- https://www.html5rocks.com/ja/tutorials/webcomponents/shadowdom-201/
- https://www.html5rocks.com/ja/tutorials/webcomponents/shadowdom-301/
- HTML imports
- https://www.html5rocks.com/ja/tutorials/webcomponents/imports/