3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

はじめに

Web Componentsは再利用可能でカプセル化されたコンポーネントを作る機能です。
Web Componentsを実装するには3つの機能を利用する必要があります。それぞれ別記事にて紹介しましたので是非ご覧ください。

  • Custom Elements コンポーネントの要素と動作を定義するための機能です。
  • Shadow DOM カプセル化を担う機能です。
  • HTML Template 再利用を可能にする機能です。
    この記事ではこれらの機能を組み合わせてWeb Componentsの実装を行います。

実装

例としてtier-tableという名前でtier表(ランキングボード)を作成する要素を作ります。細かな仕様は以下の通りです。

  •  複数の対象をA、B、Cの三段階で分類して表示する
  •  表示する内容はtier-tableの中にliを用いてslotでA、B、Cのどこに分類するか指定する
  •  表の背景色はA、B、Cのそれぞれtier-tableに属性で指定することができる

tier-tableを利用して実装したサンプルをまず紹介します。

<button id="random-color">背景色をランダムに変更する</button>
<tier-table id="tier-table" color-a="#f88"  color-b="#fb8"  color-c="#fd8">
  <li slot="tier-a">find</li>
  <li slot="tier-a">forEach</li>
  <li slot="tier-a">map</li>
  <li slot="tier-a">reduce</li>
  <li slot="tier-a">filter</li>
  
  <li slot="tier-b">concat</li>
  <li slot="tier-b">some</li>
  <li slot="tier-b">every</li>
  <li slot="tier-b">fill</li>
  <li slot="tier-b">pot</li>
  <li slot="tier-b">push</li>
  
  <li slot="tier-c">at</li>
  <li slot="tier-c">of</li>
</tier-table>
const randomButton = document.getElementById('random-color');
randomButton.addEventListener('click', () => {
  const tierTable = document.getElementById('tier-table');
  tierTable.setAttribute('color-a', randomColor());
  tierTable.setAttribute('color-b', randomColor());
  tierTable.setAttribute('color-c', randomColor());
});

function randomColor() {
  return "#" + Math.floor(Math.random() * 16777215).toString(16);
}

表示は以下のようになります。スクリーンショット 2022-12-06 22.10.23.png
小要素にリストを記述して属性を与えるだけで決まった表示を得ることができました。liの内容をフルーツの種類などに変えれば同じデザインの他の表にすることができますし、属性を変更することでデザインは変えずに背景色だけ変更した表を作ることができます。

利用例を見て作るもののイメージがついたところで実装の説明に入ります。templateは以下のようになっています。

<template id="tmp">
  <div class="ul-a">
    <p>A</p>
    <ul>
      <slot name="tier-a"></slot>
    </ul>
  </div>
  <div class="ul-b">
    <p>B</p>
    <ul>
      <slot name="tier-b"></slot>
    </ul>
  </div>
  <div class="ul-c">
    <p>C</p>
    <ul>
      <slot name="tier-c"></slot>
    </ul>
  </div>
</template>

A、B、Cごとにdivで分離してあります。pはA、B、Cの段階の説明、ulslotで受け取るリストをまとめるようなHTMLのテンプレートを作成しました。
次にtier-tableの機能の実装です。

class TierTable extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({
      mode: 'open'
    }).appendChild(document.getElementById('tmp').content.cloneNode(true));
    this.setStyle();
  }
  static get observedAttributes() {
    return ['color-a', 'color-b', 'color-c'];
  }
  attributeChangedCallback(){
    this.setStyle();
  }
  setStyle() {
    const style = document.createElement('style');
    style.textContent = `
      div { border: 1px solid }
      .ul-a { background: ${this.getAttribute('color-a')} }
      .ul-b { background: ${this.getAttribute('color-b')} }
      .ul-c { background: ${this.getAttribute('color-c')} }
    `;
    this.shadowRoot.appendChild(style);
  }
}
customElements.define('tier-table', TierTable);

constructorではtier-tableattachShadowによってShadow DOM化を行い、そこに先ほど作成したtemplateの中身をクローンしたものを割り当てています。最後に呼び出しているsetStyleはその時の属性をstyleに割り当てるものです。
さらにtier-tableでは属性の変更によってstyleを変更する必要があるのでobservedAttributesで属性を追跡してattributeChangedCallbackで属性が変化したタイミングでsetStyleを呼び出してstyleを最新のものへ変更しています。
最後にそのクラスをCustomElementRegistry.defineで登録して完了です。

これで実装は完了です。それぞれの機能を把握した後に行うととても簡単に作ることができました。tier-tableは読み込んだファイルであれば何度でもhtmlの要素のように呼び出すことが可能ですし、呼び出された中身もShadow DOMによって隠蔽(カプセル化)されました。これでWeb Componentsの作成は完了です。
サンプルの全貌は以下のCodePenを参照して下さい。

See the Pen Web Components by KokiSakano (@kokisakano) on CodePen.

UIライブラリとの比較

ReactやVueなどのUIライブラリを利用している方はWeb Componentsをわざわざ作る利点がわからなかったと思います。Web ComponentsはUIライブラリに依存していないのでどんな環境であってもコンポーネントとして利用することができるという利点があります(カプセル化されているというメリットもあります)。逆にUIライブラリではデータとDOMの同期に対して高い能力を持っており、状態管理の機能と豊富なエコシステムが整っている利点があります。どちらも一長一短ですので、それぞれに合わせたユースケースで利用して下さい。

まとめ

Web Componentsの実装を行いました。UIライブラリでは実現できなかった機能なども実現できるので状況に合わせて使ってみてはいかがでしょうか。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?