isの課題と代替案 - カスタム組み込み要素

Web Components


目次
  1. カスタム組み込み要素とは
  2. isを用いたカスタム組み込み要素の問題点
    1. Custom Attributes
  3. 追加の参考文献 

今回から3回に渡り、カスタム組み込み要素(customized built-in elements)について書いていきます。

カスタム組み込み要素とは #

一部ブラウザでis属性を用いて、標準のHTML要素を拡張したカスタム要素を作ることができる機能です。

例えば以下のようにJSとHTMLを書くと、word-countというカスタム組み込み要素を定義して利用することができます。

// HTMLParagraphElementをextendsすることに注意
class WordCount extends HTMLParagraphElement {
  constructor() {
    super();

    // いろんな処理
  }
}

customElements.define("word-count", WordCount, { extends: "p" });
<p is="word-count"></p>

こうすることで、<p>要素の動作やセマンティクスを継承しながらカスタム要素を作成することができます。 他の要素だと例えば<button>であればtype="submit"type="reset"などの機能を使うことができたり、比較的新しい機能であるpopovertargetcommandforinterestforなどの属性をカスタム要素に対して指定できるようになります。また、<label>for属性なども同様です。 今までも1つ1つ明示的に属性の同期処理などをJSで書けば可能でしたが、カスタム組み込み要素では拡張している要素の動作やセマンティクスを全て一括で継承できるところがポイントです。

また、この書き方であればJSを読み込んでいないときでもis属性を無視すれば処理を追加していないただの拡張元の標準HTML要素として扱うことができるという点もメリットの1つとして挙げられています。

読む https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Type-Extensions.md

isを用いたカスタム組み込み要素の問題点 #

isを用いたカスタム組み込み要素にはいくつか問題点があり、Webkitではopposedなpositionが取られてきています。 主に以下の問題点が挙げられます。

https://github.com/WebKit/standards-positions/issues/97 https://github.com/w3c/tpac2023-breakouts/issues/44 https://bugs.webkit.org/show_bug.cgi

これらを踏まえて、様々な代替案が検討されてきました。今回は1つ紹介します。

Custom Attributes #

Custom Property + 0 or more Custom Attributes => Custom Enhancement · Issue #1000 · WICG/webcomponentslume/custom-attributes: Define custom attributes that provide mixins for HTML elementslume/element-behaviors: An entity-component system for HTML elements.を基にしてTPAC2023のbreakoutsで議論された代替案です。その後、以下のissueでさらに話し合われました。

Custom Attributesとは、カスタム要素と同じようにカスタマイズされたHTML属性をclassを用いて作成する機能です。これをHTML要素やカスタム要素に適用し、独自の動作を当てることができるようになるというものです。 例えば以下の例だと、Attributeclassを拡張してListAttributeというカスタム属性を作成し、<input>要素で利用できるようにしています。

class ListAttribute extends Attribute {
  ownerElement; // element this is attached to
  value; // current value

  connectedCallback() {
    /* ... */
  }

  disconnectedCallback() {
    /* ... */
  }

  // Called whenever the attribute's value changes
  changedCallback() {
    /* ... */
  }

  static dataType = AttributeType.IDREF;

  // Optional default value
  static defaultValue = null;
}

HTMLInputElement.attributeRegistry.define("ac-list", ListAttribute);

今までのisではHTML要素を拡張してカスタム要素を作成し、カスタム要素に対して動作を割り当て、それをis属性に与えてしました。しかしそうではなく、HTML要素のattributeRegistryにカスタム属性を追加し、カスタム属性を通して動作を割り当てることができるようにするという提案です。

ユースケースとして

  • Popover APIやInvoker Commandsのエミュレート
  • <time>format属性をつけ、指定したフォーマットで表示されるようにする
  • <p loading-placeholder="3 sentences">のようなスケルトン表示
  • <audio start-at="0:05">のような再生開始時刻の指定

追加の参考文献  #