From e00226856d48db3618e49f857ad6af84c15636ee Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Sun, 16 Jan 2022 22:20:15 +0900 Subject: 2021/12/24 時点の英語版に同期 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web_components/using_custom_elements/index.md | 332 ++++++++++----------- 1 file changed, 155 insertions(+), 177 deletions(-) (limited to 'files/ja/web') diff --git a/files/ja/web/web_components/using_custom_elements/index.md b/files/ja/web/web_components/using_custom_elements/index.md index 359593564c..769cca7a40 100644 --- a/files/ja/web/web_components/using_custom_elements/index.md +++ b/files/ja/web/web_components/using_custom_elements/index.md @@ -1,235 +1,227 @@ --- -title: Using custom elements +title: カスタム要素の使用 slug: Web/Web_Components/Using_custom_elements tags: - - Classes - - Guide + - クラス + - ガイド - HTML - - Web Components + - ウェブコンポーネント - autonomous - - custom elements + - カスタム要素 - customized translation_of: Web/Web_Components/Using_custom_elements --- -
{{DefaultAPISidebar("Web Components")}}
+{{DefaultAPISidebar("Web Components")}} -

Webコンポーネント標準の重要な特徴の一つはカスタム要素を作れることです。それはページの機能を提供する長くネストした要素のバッチではなく、HTMLページ上で機能をカプセル化します。
- この記事はカスタム要素APIの使い方を紹介します。

+ウェブコンポーネント標準の主な特徴の 1 つは、 HTML ページに機能をカプセル化するカスタム要素を作成できることで、カスタムページの機能を提供する要素の長いネストしたバッチを作成する必要がありません。この記事では、 Custom Elements API の使い方を紹介します。 -
-

: カスタム要素をデフォルトでサポートするのは Firefox, Chrome, と Edge (76)です。Opera と Safari は今のところ、自律カスタム要素のみサポートしています。

-
+## 高水準のビュー -

High-level view

+ウェブ文書上でカスタム要素を制御するのは {{domxref("CustomElementRegistry")}} オブジェクトです。 — このオブジェクトで、ページへカスタム要素を登録したり、どのようなカスタム要素が登録されているのかを返したりすることができます。 -

Webドキュメント上でカスタム要素をコントロールするのは {{domxref("CustomElementRegistry")}} オブジェクトです。 — このオブジェクトはページへのカスタム要素を登録したり、どんなカスタム要素が登録されているのかを返すなどの操作を行えます。

+ページにカスタム要素を登録するには、 {{domxref("CustomElementRegistry.define()")}} メソッドを使います。引数に次のものを取ります。 -

ページにカスタム要素を登録するには,  {{domxref("CustomElementRegistry.define()")}} メソッドを使います。次の引数を取ることができます:

+- 要素に与える名前を表す {{domxref("DOMString")}}。カスタム要素の名前は、[ダッシュが使われている名前](https://html.spec.whatwg.org/#valid-custom-element-name) (kebab-case) である必要があります。単一の単語にすることはできません。 +- 要素の振る舞いを定義した[クラス](/en-US/docs/Web/JavaScript/Reference/Classes)のオブジェクト。 +- {{optional_inline}} `extends` プロパティを含むオプションオブジェクトです。このプロパティは、もしあれば、要素が継承する組み込み要素を指定します(カスタマイズされた組み込み要素にのみ関係します)。 - - -

例えば、次の様に word-count 要素 を定義できます:

+例えば、カスタムの [word-count 要素](https://mdn.github.io/web-components-examples/word-count-web-component/)を定義するには次のようにします。 -
customElements.define('word-count', WordCount, { extends: 'p' });
+```js +customElements.define('word-count', WordCount, { extends: 'p' }); +``` -

word-count要素は WordCountクラスのオブジェクトで {{htmlelement("p")}}要素を拡張します。

+`word-count` 要素は `WordCount` クラスのオブジェクトで、 {{htmlelement("p")}} 要素を拡張します。 -

カスタム要素のクラスオブジェクトは ES 2015 のクラスシンタックスで実装します。例えば、WordCount 次の様になります:

+カスタム要素のクラスのオブジェクトは ES 2015 のクラス構文で実装します。例えば、 `WordCount` は次のように構成します。 -
class WordCount extends HTMLParagraphElement {
+```js
+class WordCount extends HTMLParagraphElement {
   constructor() {
-    // Always call super first in constructor
+    // コンストラクターでは常に super を最初に呼び出してください
     super();
 
-    // Element functionality written in here
+    // ここに要素の機能を記述します
 
     ...
   }
-}
+} +``` -

これはごく簡単な例ですが、ここでできることはもっとあります。クラスの中でライフサイクルコールバックを定義することができ、要素のライフサイクルの特定のポイントで実行されます。例えば、connectedCallback はドキュメント接続要素にカスタム要素が追加されるたびに実行されます。一方 attributeChangedCallback はカスタム要素に属性が追加、削除、変更される時に実行されます。

+これはごく簡単な例ですが、ここでできることはもっとあります。クラスの中でライフサイクルコールバックを定義することができ、要素のライフサイクルの特定の時点で実行されます。例えば、`connectedCallback` はドキュメント接続要素にカスタム要素が追加されるたびに実行されます。一方 `attributeChangedCallback` はカスタム要素に属性が追加、削除、変更される時に実行されます。 -

{{anch("Using the lifecycle callbacks")}} でこれらについてもっと学ぶことができます。.

+これらについては、下記の{{anch("ライフサイクルコールバックの使用")}}の節で詳しく学ぶことができます。 -

カスタム要素には2つのタイプがあります:

+カスタム要素には 2 つの種類があります。 - +- スタンドアロンの**自律カスタム要素** — 標準の HTML 要素を継承しません。 HTML 要素としてページ内で記述して使います。例えば、`` あるいは `document.createElement("popup-info")` などです。 +- 基礎となる HTML 要素を継承する**カスタマイズされた組み込み要素**。これらを作成するには、どの要素を拡張するかを指定する必要があり(上記の例で示した通り)、基本要素を記述し、カスタム要素の名前を {{htmlattrxref("is")}} 属性(またはプロパティ)で指定することで使用します。されます。例えば、 `

` や `document.createElement("p", { is: "word-count" })` のようにします。 -

簡単な例と実践

+## 簡単な例での作業 -

ここで、どのようにカスタム要素をを作るのかを詳細に説明するために簡単な例を見てみましょう。

+ここで、もう少し簡単な例で、カスタム要素の作成方法をより詳しく説明しましょう。 -

自律カスタム要素

+### 自律カスタム要素 -

自律カスタム要素の例を見てみましょう — <popup-info-box>実例参照). これは画像とテキストを受け取り、ページにアイコンを埋め込みます。アイコンにフォーカスすると、ポップアップする情報ボックスにテキストを表示してコンテキスト内の情報を更に提供します。

+自律カスタム要素の例を見てみましょう。[``](https://github.com/mdn/web-components-examples/tree/master/popup-info-box-web-component) ([ライブ例](https://mdn.github.io/web-components-examples/popup-info-box-web-component/)も参照) です。これは画像とテキストを受け取り、ページにアイコンを埋め込みます。アイコンにフォーカスすると、テキストをポップアップ情報ボックスに表示し、さらにコンテキスト内の情報を提供します。 -

最初に{{domxref("HTMLElement")}}を継承して PopUpInfo,というクラスを定義します。 自律カスタム要素はほぼいつも HTMLElementを継承します。

+最初に汎用的な {{domxref("HTMLElement")}} クラスを継承して `PopUpInfo` というクラスを定義する JavaScript ファイルです。 -
class PopUpInfo extends HTMLElement {
+```js
+class PopUpInfo extends HTMLElement {
   constructor() {
-    // Always call super first in constructor
+    // コンストラクターでは常に super を最初に呼び出してください
     super();
 
-    // write element functionality in here
+    // ここに要素の機能を記述します
 
     ...
   }
-}
+} +``` -

前述のコードスニペットはクラスの constructor() の定義を含んでおり、常に super() を最初に呼び出します。これにより正しいプロタイプチェーンが確立されます。

+前述のコードスニペットはクラスのコンストラクター ([`constructor()`](/ja/docs/Web/JavaScript/Reference/Classes/constructor)) の定義を含んでいます。ここでは常に [`super()`](/en-US/docs/Web/JavaScript/Reference/Operators/super) を最初に呼び出し、正しい正しいプロタイプチェーンが確立されるようにします。 -

コンストラクタ内で、インスタンス化された時に要素が持っているすべての機能を定義します。この例ではカスタム要素にshadowルートをアタッチしています。DOM操作を行い、要素内部の shadow DOM構造を作ります。—DOM構造はshadowルートにアタッチされます— そして最後にスタイルを適用するためにCSSをshadowルートにアタッチします。

+コンストラクターの内部では、その要素のインスタンスが生成されたときに持つすべての機能を定義します。この場合、カスタム要素にシャドウルートを添付し、いくつかの DOM 操作を使用して要素の内部シャドウ DOM 構造を作成します。それをシャドウルートに添付します。そして最後に、いくつかの CSS をシャドウルートに添付してスタイル付けを行います。 -
// Create a shadow root
-var shadow = this.attachShadow({mode: 'open'});
+```js
+// シャドウルートを生成
+this.attachShadow({mode: 'open'}); // 'this.shadowRoot' を設定して返す
 
-// Create spans
-var wrapper = document.createElement('span');
+// (内部の) span 要素を生成
+const wrapper = document.createElement('span');
 wrapper.setAttribute('class','wrapper');
-var icon = document.createElement('span');
+const icon = wrapper.appendChild(document.createElement('span'));
 icon.setAttribute('class','icon');
 icon.setAttribute('tabindex', 0);
-var info = document.createElement('span');
-info.setAttribute('class','info');
-
-// Take attribute content and put it inside the info span
-var text = this.getAttribute('text');
-info.textContent = text;
-
-// Insert icon
-var imgUrl;
-if(this.hasAttribute('img')) {
-  imgUrl = this.getAttribute('img');
-} else {
-  imgUrl = 'img/default.png';
-}
-var img = document.createElement('img');
-img.src = imgUrl;
-icon.appendChild(img);
+// アイコンを、定義された属性または既定のアイコンから挿入
+const img = icon.appendChild(document.createElement('img'));
+img.src = this.hasAttribute('src') ? this.getAttribute('src') : 'img/default.png';
 
-// Create some CSS to apply to the shadow dom
-var style = document.createElement('style');
+const info = wrapper.appendChild(document.createElement('span'));
+info.setAttribute('class','info');
+// 属性の中身を取得し、 info の span の中に入れる
+info.textContent = this.getAttribute('data-text');
 
+// CSS を作成しシャドウ DOM に割り当てる
+const style = document.createElement('style');
 style.textContent = '.wrapper {' +
-// CSS truncated for brevity
+// 簡略化のために CSS は省略
 
-// attach the created elements to the shadow dom
-
-shadow.appendChild(style);
-shadow.appendChild(wrapper);
-wrapper.appendChild(icon);
-wrapper.appendChild(info);
+// 生成された要素をシャドウ DOM に添付する +this.shadowRoot.append(style,wrapper); +``` -

最後に、カスタム要素を CustomElementRegistry に登録します。前述の define() を使用して、パラメーターで要素名とその機能を定義するクラス名を指定します:

+最後に、カスタム要素を `CustomElementRegistry` に登録します。前述の `define()` を使用して、引数で要素名とその機能を定義するクラス名を指定します。 -
customElements.define('popup-info', PopUpInfo);
+```js +customElements.define('popup-info', PopUpInfo); +``` -

これによってページで使えるようになりました。HTML中で下記のように使用することができます。

+これによって要素がページで使えるようになりました。 HTML 中で下記のように使用することができます。 -
<popup-info img="img/alt.png" text="Your card validation code (CVC)
+```html
+
+  back of your card.">
+```
 
-
-

: こちらで 完全なソースコード を見ることができます。

-
+> **Note:** こちらで[完全な JavaScript ソース](https://github.com/mdn/web-components-examples/blob/master/popup-info-box-web-component/main.js) を見ることができます。 -
-

: カスタム要素が機能するためには、DOMの解析を終えた後にカスタム要素を登録するスクリプトが読み込まれる必要があることに注意してください。これは <script> 要素を <body> 要素内の最下部に配置する、または <script> 要素に defer 属性を加えることで解決します。

-
+### 内部スタイルと外部スタイル -

内部スタイル 対 外部スタイル

+上記の例では {{htmlelement("style")}} 要素を用いてシャドウ DOM にスタイルを適用しましたが、代わりに完全に {{htmlelement("link")}} 要素から外部スタイルシートを参照することが可能です。 -

上記の例では {{htmlelement("style")}} 要素を用いてShadow DOMにスタイルを適用しました。しかし、{{htmlelement("link")}} 要素から外部のスタイルシートを参照することも可能です。

+例えば、 [popup-info-box-external-stylesheet](https://mdn.github.io/web-components-examples/popup-info-box-external-stylesheet/) のコードを少し見てみましょう([ソースコード](https://github.com/mdn/web-components-examples/blob/master/popup-info-box-external-stylesheet/main.js)はこちら)。 -

例えば、popup-info-box-external-stylesheet のコードを少し見てみましょう(ソースコード)。

- -
// Apply external styles to the shadow dom
+```js
+// 外部スタイルシートをシャドウ DOM に適用
 const linkElem = document.createElement('link');
 linkElem.setAttribute('rel', 'stylesheet');
 linkElem.setAttribute('href', 'style.css');
 
-// Attach the created element to the shadow dom
+// 生成された要素をシャドウ DOM に添付
 shadow.appendChild(linkElem);
-
+``` + +なお、 {{htmlelement("link")}} 要素はシャドウルートの描画をブロックしないので、スタイルシートのロード中にスタイル付けされていないコンテンツ (FOUC) が一瞬表示されるかもしれないことに注意してください。 -

この手法が特に大規模なスタイルシートで推奨されます。これによって、綺麗で、より共有しやすい効率の良いコードになります。

+最近のブラウザーの多くは、共通のノードからクローンされた、あるいは同一のテキストを持つ {{htmlelement("style")}} タグに対して、単一のバッキングスタイルシートを共有できるようにする最適化を実装しています。この最適化によって、外部スタイルでも内部スタイルでも性能は同程度になるはずです。 -

カスタマイズされたビルトイン要素

+### カスタマイズされた組み込み要素 -

ここで、もう1つのビルトイン要素の例を見てみましょう — expanding-list (デモはこちら) 。 これにより番号なしリストが展開・縮小するメニューになります。
-
- まず始めに、これまでと同様の規則でクラス要素を定義します。

+ここで、もう 1 つの組み込み要素の例を見てみましょう。 [expanding-list](https://github.com/mdn/web-components-examples/tree/master/expanding-list-web-component) ([ライブでも確認してください](https://mdn.github.io/web-components-examples/expanding-list-web-component/)) です。 これにより番号なしリストが展開・縮小するメニューになります。 -
class ExpandingList extends HTMLUListElement {
+ まず始めに、これまでと同様の方法でクラス要素を定義します。
+
+```js
+class ExpandingList extends HTMLUListElement {
   constructor() {
-    // Always call super first in constructor
+    // コンストラクターでは常に super を最初に呼び出してください
     super();
 
-    // write element functionality in here
+    // ここに要素の機能を記述します
 
     ...
   }
-}
+} +``` -

ここでは要素の詳細な機能については説明しませんが、ソースコードからどのように動作するのかチェックすることができます。これまでと唯一違う点は {{domxref("HTMLElement")}} ではなく、 {{domxref("HTMLUListElement")}} インターフェースを拡張していることです。そのため、独立した要素ではなく、 {{htmlelement("ul")}} 要素の特徴を備えた上に、私たちが定義した機能を持っています。これこそが自律カスタム要素ではなくカスタマイズされたビルトイン要素である理由です。
-
- 次に、以前と同様に define() を用いて要素を登録するのですが、今回はこのカスタム要素がどの要素から継承したのかという情報をオプションとして渡しています。

+ここでは要素の詳細な機能については説明しませんが、ソースコードからどのように動作するのか確認することができます。これまでと唯一違う点は、 {{domxref("HTMLUListElement")}} インターフェースを継承しており、 {{domxref("HTMLElement")}} ではないことです。そのため、独立した要素ではなく、 {{htmlelement("ul")}} 要素の特徴を備えた上に、定義した機能を持ちます。これこそが、自律カスタム要素ではなくカスタマイズされた組み込み要素である理由です。 -
customElements.define('expanding-list', ExpandingList, { extends: "ul" });
+ 次に、以前と同様に `define()` を用いて要素を登録しますが、今回はこのカスタム要素がどの要素から継承したのかという情報をオプションとして渡しています。 -

Webドキュメント内でビルトイン要素を使用する場合とはやや異なります。

+```js +customElements.define('expanding-list', ExpandingList, { extends: "ul" }); +``` -
<ul is="expanding-list">
+ウェブ文書内で組み込み要素を使用する場合とはやや異なります。
+
+```html
+
    ... -</ul>
+ +``` + +通常のように `
    ` を使用していますが、カスタム要素の名前が `is` 属性で指定されています。 -

    通常のように <ul> を使用していますが、カスタム要素の名前が is 属性で指定されています。

    +> **Note:** 繰り返しますが、完全な [JavaScript のソースコード](https://github.com/mdn/web-components-examples/blob/master/expanding-list-web-component/main.js)はこちらにあります。 -
    -

    : もう一度述べますが、こちらで 完全なソースコード を見ることができます。

    -
    +## ライフサイクルコールバックの使用 -

    ライフサイクルコールバックの使用

    +カスタム要素のクラス定義内に、いくつかの異なるコールバックを定義できます。これらは要素のライフサイクルのさまざまな時点で起動します。 -

    カスタム要素のクラス定義内にいくつかの異なるコールバックを定義できます。これらのコールバックは、要素のライフサイクルのさまざまな時点で起動します。

    +- `connectedCallback`: 文書に接続された要素にカスタム要素が追加されるたびに呼び出されます。これはそのノードが移動するために発生するので、要素の内容が完全に解釈される前に発生することがあります。 -
      -
    • connectedCallback: カスタム要素がドキュメントに接続された要素に追加されるたびに呼び出されます。これは、ノードが移動されるたびに発生し、要素のコンテンツが完全に解析される前に発生する場合があります。 -
      -

      : エレメントが接続されなくなったらconnectedCallback を呼び出すことができます,  {{domxref("Node.isConnected")}} を使用して確認してください.

      -
      -
    • -
    • disconnectedCallback: カスタム要素がドキュメントのDOMから切断されるたびに呼び出されます。
    • -
    • adoptedCallback: カスタム要素が新しいドキュメントに移動するたびに呼び出されます。
    • -
    • attributeChangedCallback: カスタム要素の属性の1つが追加、削除、または変更されるたびに呼び出されます。変更を通知する属性は、 static get observedAttributes() メソッドで指定されます
    • -
    + > **Note:** `connectedCallback` は要素の接続が終了したときにも呼び出されることがあります。 {{domxref("Node.isConnected")}} を使用して確認してください。 -

    使用中のこれらの例を見てみましょう。以下のコードは、ライフサイクルコールバックの例から取ったものです(ライブ実行を参照)。これは、ページ上に固定サイズの色付きの正方形を生成する単純な例です。カスタム要素は次のようになります。

    +- `disconnectedCallback`: カスタム要素が文書の DOM から切断されるたびに呼び出されます。 +- `adoptedCallback`: カスタム要素が新しい文書に移動するたびに呼び出されます。 +- `attributeChangedCallback`: カスタム要素の属性の 1 つが追加、削除、変更されるたびに呼び出されます。どの属性の変更が通知されたかは、 static get `observedAttributes()` メソッドで指定されます。 -
    <custom-square l="100" c="red"></custom-square>
    +これらの使用例を見てみましょう。以下のコードは [life-cycle-callbacks](https://github.com/mdn/web-components-examples/tree/master/life-cycle-callbacks) の例から引用しています ([実行可能なライブでも確認してください](https://mdn.github.io/web-components-examples/life-cycle-callbacks/))。これは、ページ上に一定の大きさの色のついた四角形を生成する些細な例です。カスタム要素は次のようなものです。 -

    クラスコンストラクターは非常に単純です。ここでは、要素にシャドウDOMをアタッチし、空の{{htmlelement("div")}} および{{htmlelement("style")}} 要素をシャドウルートにアタッチします:

    +```html + +``` -
    var shadow = this.attachShadow({mode: 'open'});
    +クラスのコンストラクターは非常に単純です。ここでは、要素にシャドウ DOM を割り当て、空の {{htmlelement("div")}} および {{htmlelement("style")}} 要素をシャドウルートに追加します。
     
    -var div = document.createElement('div');
    -var style = document.createElement('style');
    +```js
    +const shadow = this.attachShadow({mode: 'open'});
    +
    +const div = document.createElement('div');
    +const style = document.createElement('style');
     shadow.appendChild(style);
    -shadow.appendChild(div);
    +shadow.appendChild(div); +``` -

    この例の主要な機能はupdateStyle()です。これは要素を取得し、シャドウルートを取得し、その<style>要素を見つけて、{{cssxref("width")}}, {{cssxref("height")}}, および{{cssxref("background-color")}} をスタイルに追加します。

    +この例の主要な機能は `updateStyle()` です。これは要素を取得し、シャドウルートを取得し、その `