モバイル対応のコンポーネント
LWC でのサードパーティ Web コンポーネントの使用 (ベータ)
カスタム要素の使用 (ベータ)
カスタム要素にデータを渡す (ベータ)
カスタム要素へのスタイルの追加 (ベータ)
カスタム要素は、サードパーティ Web コンポーネントの構成要素です。カスタム要素にデータを渡すには、属性、プロパティ、または lwc:spread ディレクティブを使用します。データを渡すと、LWC ではデフォルトでデータが属性として設定されます。プロパティは存在する場合にのみ設定されます。
this.attachShadow({ mode: 'closed' }) を使用してシャドウコンテンツを初期化するコンストラクタは、一度だけ呼び出されます。属性やプロパティを使用する場合には、次のガイドラインに留意してください。
サードパーティ Web コンポーネントが表示された後は、属性の変更が無視されます。属性を監視し、サードパーティ Web コンポーネントに確実に変更を表示するには、observedAttributes() 静的 getter 関数と attributeChangedCallback() メソッドを使用します。attributeChangedCallback() コールバックは、監視している属性が変更されたときに実行されます。属性データのシリアライズとデシリアライズを処理するには、次の例のように getter および setter を使用します。
1class extends HTMLElement {
2 static observedAttributes = ["myAttr"];
3 attributeChangedCallback(attr, oldVal, newVal) {
4 if (attrName === "myAttr") {
5 this.shadow.getElementById("myElement").myAttr = newVal === "true";
6 }
7 }
8 set myAttr(bool) {
9 this.setAttribute("myAttr", bool.toString());
10 }
11 get myAttr() {
12 return this.getAttribute("myAttr") === "true";
13 }
14}属性の変更によってボタンのカウントを増分する例については、こちらを参照してください。
プロパティを利用する場合は、getter および setter を使用します。
1class extends HTMLElement {
2 _message = 'Hello';
3 set message(value) {
4 this._message = value;
5 }
6 get message() {
7 return this._message;
8 }
9}たとえば、lwc:spread ディレクティブを使用してプロパティに渡されるカスタム要素があるとします。
1<!-- myMessage.html -->
2<template>
3 <c-message lwc:external lwc:spread={props}></c-message>
4</template>このカスタム要素はボタンを表示します。ボタンにイベントリスナーを追加するには、addEventListener() を使用します。
1// myMessage.js
2import { LightningElement } from "lwc";
3
4customElements.define(
5 "c-message",
6 class extends HTMLElement {
7 constructor() {
8 super();
9 this.shadow = this.attachShadow({ mode: "closed" });
10 this.shadow.innerHTML = `<button>click</button>`;
11 this.shadow.querySelector("button").addEventListener("click", (event) => {
12 console.log(`message: ${this.message}`);
13 });
14 }
15
16 set message(value) {
17 this._message = value;
18 }
19 get message() {
20 return this._message;
21 }
22 },
23);
24
25export default class MyMessage extends LightningElement {
26 props = {
27 message: "Hello custom element",
28 };
29}親コンポーネントに、カスタム要素を定義した子コンポーネントが含まれているとします。lwc:spread ディレクティブを使用して、子コンポーネントにプロパティを渡します。
1<!-- myApp.html -->
2<template>
3 <c-cmp lwc:spread="{myProps}"></c-cmp>
4</template>キーと値のペアを持つオブジェクトを使用します。
1// myApp.js
2import { LightningElement } from "lwc";
3
4export default class MyApp extends LightningElement {
5 myProps = {
6 name: "Guest",
7 greeting: "Hello",
8 };
9}子コンポーネントで、カスタム要素のインスタンスを作成します。
1<!-- myCmp.html -->
2<template>
3 <c-custom-el lwc:external> {greeting}, {name} </c-custom-el>
4</template>JavaScript で constructor() をコールして、プロパティを親コンポーネントに公開します。
1// myCmp.js
2import { LightningElement, api } from "lwc";
3
4customElements.define(
5 "c-custom-el",
6 class extends HTMLElement {
7 constructor() {
8 super();
9 this.attachShadow({ mode: "closed" }).innerHTML = "<slot></slot>";
10 }
11 },
12);
13export default class MyCmp extends LightningElement {
14 @api name;
15 @api greeting;
16}カスタム要素は次のように表示されます。
1<my-app>
2 #shadow-root (open)
3 | <my-cmp>
4 | #shadow-root (open)
5 | | <c-custom-el>
6 | | #shadow-root (closed)
7 | | | Hello, Guest
8 | | </c-custom-el>
9 | </my-cmp>
10</my-app>サードパーティ Web コンポーネントのスロットにマークアップを渡す操作は、LWC コンポーネントのスロットの場合と似ています。
合成 Shadow のスロット実装は、サードパーティ Web コンポーネントではサポートされていません。
Note
サードパーティ Web コンポーネントにいくつかのマークアップがあるとします。
1customElements.define(
2 "c-custom-slot",
3 class extends HTMLElement {
4 constructor() {
5 super();
6 this.attachShadow({ mode: "closed" }).innerHTML = `
7 <h1>My title</h1>
8 <div>
9 <p>Some content here</p>
10 </div>
11 <slot></slot>
12 `;
13 }
14 },
15);次のスロット化されたコンテンツが <slot> 要素に表示されます。
1<template>
2 <c-custom-slot lwc:external>
3 <div class="slotted">slot content</div>
4 </c-custom-slot>
5</template>コンポーネントは DOM で次のように表示されます。
1<c-custom-slot>
2 #shadow-root (closed)
3 | <h1>My title</h1>
4 | <div><p>Some content here</p></div>
5 | <slot>
6 | <div class="slotted">slot content</div>
7 | </slot>
8</c-custom-slot>同様に、名前付きスロットを次のように使用することができます。
1// mySlot.js
2import { LightningElement, api } from "lwc";
3
4customElements.define(
5 "c-slotting",
6 class extends HTMLElement {
7 constructor() {
8 super();
9 this.shadow = this.attachShadow({ mode: "closed" });
10 this.shadow.innerHTML = `<slot name="myslot"></slot>`;
11 }
12 },
13);
14export default class MySlot extends LightningElement {}マークアップに名前付きスロットを含めます。
1<!-- mySlot.html -->
2<c-slotting lwc:external>
3 <p>slotted incorrectly</p>
4 <p slot="myslot">slotted correctly</p>
5</c-slotting>コンポーネントは DOM で次のように表示されます。
1<my-slot>
2 #shadow-root (open)
3 | <c-slotting>
4 | #shadow-root (closed)
5 | | <p>slotted incorrectly</p>
6 | | <p slot="myslot">slotted correctly</p>
7 | </c-slotting>
8</my-slot>サードパーティ Web コンポーネントのイベントは、LWC のイベントと同じように動作します。イベントのバインドは、小文字のイベントについてのみサポートされます。小文字以外を使った名前のイベントを使用するには、addEventListener() API を使用するイベントリスナーを追加します。
constructor() にイベントリスナーを追加します。
1customElements.define(
2 "c-element-with-events",
3 class extends HTMLElement {
4 constructor() {
5 super();
6 this.attachShadow({ mode: "closed" });
7 this.shadow.innerHTML = `CLICK ME!`;
8 this.addEventListener("click", this.handleClick);
9 }
10 handleClick() {
11 this.dispatchEvent(new CustomEvent("lowercaseevent"));
12 this.dispatchEvent(new CustomEvent("camelEvent"));
13 }
14 },
15);登録されていないカスタム要素は、ネイティブの HTMLUnknownElement インターフェースのインスタンスとして表示されます。このインターフェースは、HTMLElement を拡張したのもですが、プロパティやメソッドは追加されていません。ブラウザでは、外部コンポーネントが span や div と同様のネイティブコンポーネントとして処理されます。
登録済みのコンポーネントの場合、エンジンが関連するサードパーティ Web コンポーネントを表示し、ブラウザでのアップグレードを遅延させます。
詳細は、HTML 仕様の「Upgrading elements after their creation (要素を作成した後のアップグレード)」を参照してください。
さらに、サードパーティ Web コンポーネントに関するアップグレードの動作についても考慮してください。
The Japanese Summer '24 guide is now live