イベント伝達の設定
起動されたイベントは、DOM ツリー内で上方向に伝達できます。どこでイベントが処理されるかを理解するには、イベントがどのように伝達するかを理解してください。
イベントは DOM によって上に伝達されます。これが親子の通信方法で、プロパティは下方向、イベントは上方向に伝達されます。イベントは伝達すると、コンポーネントの API の一部となり、イベントのパス沿いのすべてのコンシューマがイベントを理解する必要があります。伝達のしくみを理解して、目的のコンポーネントで機能する伝達設定の中で最も制限の厳しいものを選択できるようにすることが重要です。
Lightning Web コンポーネントイベントは、DOM イベントと同じルールに従って伝達されます。Lightning Web コンポーネントでは伝達フェーズのみが使用されます。捕捉フェーズへのイベントのディスパッチやリスナーの追加はサポートされていません。イベントのパスは、単純に自分のコンポーネントから始まって、親、そしてその親へと移動するものと考えることができます。
イベントの対象は、コンポーネントインスタンスのシャドウルートを超えては伝達されません。コンポーネントの外部からは、すべてのイベント対象はコンポーネント自体です。一方、シャドウツリーの内部では、ツリー内の特定の対象からのイベントを処理できます。イベントのリスナーを接続する場所とイベントが発生する場所に応じて、異なる対象を設定できます。
このコンテンツは、Salesforce 開発者ブログの記事「How Events Bubble in Lightning Web Components (Lightning Web コンポーネントでのイベントバブルの仕組み)」から引用しています。
イベントを作成するときには、イベントで bubbles
と composed
の 2 つのプロパティを使用してイベント伝達動作を定義してください。
-
Event.bubbles
イベントが DOM ツリーを上に伝達するかどうかを示す Boolean 値。デフォルト設定は
false
です。 -
Event.composed
イベントがシャドウ境界を越えることができるかどうかを示す Boolean 値。デフォルト設定は
false
です。
イベントに関する情報を取得するには、Event Web API の次のプロパティとメソッドを使用します。
-
Event.target
イベントをディスパッチした要素。
各コンポーネントの内部 DOM は、Shadow DOM でカプセル化されます。シャドウ境界は通常の DOM (Light DOM とも呼ばれる) と Shadow DOM との間の線です。イベントが上に伝達してシャドウ境界を横断した場合は、
Event.target
の値がリスナーの範囲に応じた要素を表すように変更されます。イベントの対象が変更されても、コンポーネントのカプセル化が維持され、コンポーネントの内部情報が流出するのを防ぎます。たとえば、
<my-button>
に対するクリックリスナーは、クリックがbutton
要素に対して発生した場合でも、常にmy-button
を対象として受け取ります。 -
Event.currentTarget
イベントが DOM をトラバースするときに、このプロパティは常にイベントハンドラが接続されていた要素を参照します。
-
Event.composedPath()
イベントが DOM をトラバースするときに、リスナーが呼び出されるイベント対象の配列。
静的構成では、スロットが使用されません。次の簡単な例では、c-app
が c-parent
を構成し、これが c-child
を構成します。
アプリの親コンポーネントは、ボタンのクリックを処理します。
親コンポーネントには、子コンポーネントを含むラッパーがあり、両方でボタンのクリックイベントをリスンしています。
子コンポーネントには、onclick
ハンドラを含むボタンがあります。
この例では、ボタンがクリックされたとき c-child
から buttonclick
イベントを発生します。イベントリスナーは、次の要素のカスタムイベントに接続されます。
body
c-app
ホストc-parent
div.wrapper
c-child
ホスト
フラット化されたツリーは次のようになります。
デフォルト設定。イベントは DOM ツリーを上に伝達せず、シャドウ境界を越えることもありません。このイベントをリスンする唯一の方法は、イベントをディスパッチするコンポーネントに直接イベントリスナーを追加することです。
この設定では混乱が最小限に抑えられ、コンポーネントのカプセル化が最良になるため、お勧めします。
イベントが c-child
のみまで上に伝達されます。
c-child
ハンドラを検査すると、イベントで次の値が返されます。
event.currentTarget
=c-child
event.target
=c-child
ここから、以降のいくつかのセクションでは、構成の制約が少ない実装を開始できます。
lwc-recipes リポジトリの c-event-with-data
コンポーネントは、bubbles: false
と composed: false
の設定でイベントを作成する c-contact-list-item
コンポーネントを消費します。
イベントは DOM ツリーを上に伝達しますが、シャドウ境界は越えません。その結果、c-child
と div.wrapper
の両方がイベントに反応する可能性があります。
イベントハンドラは次の値を返します。
c-child
ハンドラ
event.currentTarget
=c-child
event.target
=c-child
div.childWrapper
ハンドラ
event.currentTarget
=div.childWrapper
event.target
=c-child
この設定には 2 つの使用事例があります。
-
内部イベントの作成
コンポーネントのテンプレート内でイベントを上に伝達させるには、テンプレート内の要素でイベントをディスパッチします。イベントは、テンプレート内のみで要素の上位コンポーネントまで上に伝達します。イベントは、シャドウ境界に達すると上への伝達を停止します。
イベントは
myComponent.js
で処理する必要があります。イベントはシャドウ境界を越えないため、コンテナコンポーネントのハンドラは実行されません。 -
コンポーネントの祖父母へのイベントの送信
コンポーネントがスロットに渡され、イベントをそのコンポーネントからコンポーネントを含むテンプレートまでイベントを伝達させる必要がある場合には、ホスト要素でイベントをディスパッチします。イベントは、コンポーネントを含むテンプレートでのみ表示可能です。
lwc-recipes リポジトリの
eventBubbling
コンポーネントを要約したサンプルコードを見てみましょう。子から祖父母へのコンポーネント階層はc-contact-list-item-bubbling -> lightning-layout-item -> c-event-bubbling
です。c-contact-list-item-bubbling
コンポーネントは、bubbles: true
のカスタムイベントcontactselect
をディスパッチします。イベントリスナー
oncontactselect
は親lightning-layout-item
上にあり、イベントは祖父母c-event-bubbling
で処理されます。
イベントは DOM ツリーを上に伝達し、シャドウ境界を越えて、ドキュメントのルートまで上に伝達します。
イベントをこのように設定すると、イベント種別はコンポーネントの公開 API の一部となります。また、コンシューマであるコンポーネントとそのすべての上位コンポーネントの API の一部としてイベントが強制的に含まれます。
この設定では、イベントがドキュメントのルートまで上に伝達するため、名前の競合が発生することがあります。名前の競合により、正しくないイベントリスナーが起動することがあります。
この設定を使用する場合は、mydomain__myevent
のように名前空間をプレフィックスとしてイベント種別に付加します。HTML イベントリスナー名は onmydomain__myevent
のようなおかしな名前になります。
Lightning Web コンポーネントはこの設定を使用しません。
関連トピック
- Javascript.info: Introduction to Events (イベント概論): Bubbling and capturing (バブリングとキャプチャリング)
- Shadow DOM