プログラミング

Web Components: カスタム属性の利用方法

投稿日:2019年12月18日 更新日:

1. はじめに

Web Components を使ってカスタム要素を作成し、そのタグを記述する際に、独自の属性を利用する方法について説明します。

例えば、あるカスタム要素を<my-element>というタグとして利用する場合に、foobarという属性を指定したいのであれば、以下のように書けます。

<my-element foobar="10"></my-element>

カスタム要素を実装するためのクラス定義において、プロパティとして実装することが合理的である値があった場合に、先程のような「HTMLタグの属性」をそのオブジェクトのプロパティとして透過的に利用するこができれば、処理の実装がラクになります(*1)。また、HTMLタグにあらかじめ属性値を指定しておくことで、プロパティの初期値として利用することができます。

本記事では、Web Components のカスタム要素において、属性値をプロパティとして利用する方法について説明します。

(*1)
this.getAttribute(属性名)の代わりにthis.属性名で値を参照できたり、this.setAttribute(属性名, 値)の代わりに、this.属性名 = 値と値を代入できてラクです。しかも、属性値は文字列しか使えませんが、プロパティはいろいろな型の値が使えます。

2. カスタム属性の使い方

基本的なコード例

ここでは、カスタム要素で rate という属性を使うコードの例を紹介します。属性値は文字列型しかとれないのですが、rate という属性は整数として利用したいので、何箇所かで型変換を行っていることにも注意してください。

最終的に、以下のようなHTMLタグを記述すると想定します。

<my-element rate="1">Default</my-element>

カスタム要素のクラス定義をモジュールとして使えるように、my-element.js という名前のファイルに以下を記述します。コメントに各コードの説明を書いておきました。

export default class extends HTMLElement {
  constructor() {
    super();
    // 省略
  }

  /* カスタム要素が DOM に追加されたときに実行されます。 */
  connectedCallback() {
    // getter が定義されているので、this.rate で値が参照できます(getterが実行されます)。
    if (!Number.isInteger(this.rate)) {
      // setter が定義されているので、「this.rate = 値」で値をセットできます
      this.rate = 1; // setter が実行されます
    }
  }

  /* Getter */
  get rate() {
    // 属性値を取得し、整数に変換して返します
    return parseInt(this.getAttribute('rate'));
  }

  /* Setter */
  set rate(value) {
    // 渡された値を属性値として保持します
    // ここで数値をセットしても属性値は文字列になります(自動変換)
    this.setAttribute('rate', value);
  }

  // 省略
};
  • 「get 属性名()」でプロパティの Getter を定義しています。
  • 「set 属性名(値)」でプロパティの Setter を定義しています。
  • 実際には connectedCallback()の後半やその他のメソッド内で、this.rate を使った処理があるはずという想定です。

HTMLファイルには以下を記述します。

<!-- 目的の位置にカスタム要素のタグを記述します -->
<my-elm rate="1">Default</my-elm>

<script type="module">
// カスタムクラスをインポートします
import MyElement from './my-element.js';
// カスタムクラスにタグ名をつけます
customElements.define('my-element', MyElement);
</script>

attributeChangedCallback() を使う場合

特定の属性値が「追加」「削除」「変更」された時に発火する attributeChangedCallback() というメソッドも使えます。

そのためには、まずクラス定義の中で、observedAttributes() メソッドを実装します。

  static get observedAttributes() {
    return ['rate'];
  }

戻り値となる配列には、監視対象にするプロパティ名をセットします。

そして、attributeChangedCallback() メソッドを実装します。

  /*
   * @param {string} name - 属性名
   * @param {string} oldValue - 元の値
   * @param {string} newValue - 新しい値
   */
  attributeChangedCallback(name, oldValue, newValue) {
    // 何かしらプロパティに関する処理
    console.log(name, oldValue, newValue);
  }

このメソッドでは、引数として渡された属性値に付随するその他の属性値をセット・変更するのに使われることが多いようです。例えば、引数で渡された属性値に合った tabindex属性や Web Accessibility Initiative (WAI) の属性などをセットします。カスタム要素 v1: 再利用可能なウェブ コンポーネント  |  Web  |  Google Developers にもその例が載っています。

値がいらない属性 (disabledなど)の場合

HTMLタグの属性には値がいらないものがあります。例えば、disabledです。

<my-elm disabled>Default</my-elm>

カスタム要素 v1: 再利用可能なウェブ コンポーネント  |  Web  |  Google Developers には、この手の属性をプロパティとして利用する場合のコードが載っています。そこに載っているdisabled属性の Getter / Setter が以下です。

カスタム要素 v1: 再利用可能なウェブ コンポーネント から抜粋 (※ コメントはこちらで追加)

  /*
   * disabled の Getter
   * @returns {boolean}
   */
  get disabled() {
    // True/False を返すため hasAttribute() を使っています
    return this.hasAttribute('disabled');
  }

  /*
   * disabled の Setter
   */
  set disabled(val) {
    if (val) {
      // disabled属性に値は必要ないので、'' をセットしています
      this.setAttribute('disabled', '');
    } else {
      // 「disabled が False である」とは、
      // disabled 属性自体の記述がないことになるので、
      // disabled 属性を削除しています
      this.removeAttribute('disabled');
    }
  }

コメントにも説明を書きましたが、「HTMLタグの disabled属性の記述」と「HTMLElement のプロパティとしての扱い (Boolean)」の差異を Getter / Setter で上手く変換しています。

3. おわりに

Web Components のカスタム要素を作成する場合、「独自の属性を追加して利用する」というのは割と頻繁に行うことになると思います。まだこのあたりについて参考になる文献も少ないので、本記事にまとめてみました。

4. 参考

Web Components

Web Components: 組み込み要素を拡張する方法

2019.12.18
Web Components

Web Components: Shadow DOM に HTML と CSS をセットするいろいろな方法

2019.12.17
Web Components

Web Components の Slot について

2019.12.17

📂-プログラミング
-

執筆者:labo


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Web Programming

アクセス元のグローバルIPアドレスが表示されるだけのWebページを作る (Content-Type を変えた2種類)(PHP利用)

目次1. はじめに2. 手順(HTMLバージョン)(1) ウェブサーバー上にディレクトリを用意します(2) index.php ファイルを作成します(3) この Webページにアクセスします3. 手順 …

Babel とは?

目次1. Babel とは?2. JavaScript のバージョン3. プラグイン (plugins)4. プリセット (preset)5. 基本的な使い方6. Babel のイメージ 1. Bab …

フレームレートを指定して Canvas に描画するサンプルページを作りました

フレームレートを指定して Canvas に描画するサンプルページを作りました。 目次1. スクリーンショット2. デモ3. 説明4. ソースコード 1. スクリーンショット スクリーンショット 2. …

Webページ上に問題と解答を記載し、解答はボタンで表示する方法

ブログも含め Webページ上で、問題と解答を記載したいのだけれど、解答はすぐに見せたくない場合の方法です。用意したボタンをクリックすると、JavaScriptのプログラムが実行されて解答を表示させます …

Web Components

Web Components: Shadow DOM に HTML と CSS をセットするいろいろな方法

Web Components の Shadow DOM を使う場合のファイル構成やコードについて、いろいろなパターンを紹介します(最小限のコードのみです)。