イベントとの通信
学習の目的
- 2 つのプログラミングモデルのイベントの違いを説明する。
- Lightning Web コンポーネントから Aura コンポーネントにイベントを送信する。
壁で囲まれた単体のコンポーネントは便利かもしれませんが、コンポーネント間で通信が行われるときに本当のアプリケーションの魔法が起こります。そこで重要なのがイベントです。コンポーネント間の通信にイベントを使用するのは Web 標準であり、Aura コンポーネントと Lightning Web コンポーネントのどちらにおいてもイベントは通信の中核です。
コンポーネントイベントは DOM イベントになる
Aura コンポーネントのコンポーネントイベントを Lightning Web コンポーネントの Web 標準 DOM イベントに移行します。DOM イベントについて理解している方は、Lightning Web コンポーネントでは同じ伝達動作をすることがわかるでしょう。
イベントの作成とディスパッチ
Aura コンポーネント専有の Event オブジェクトの代わりに、Event または CustomEvent 標準 DOM インターフェースを使用します。より一貫性のあるエクスペリエンスが提供されるため、CustomEvent インターフェースを使用することを強くお勧めします。フレームワークは、ブラウザー間の実装を正規化するために、イベントのプロパティとメソッドにパッチを適用しなければならない場合があります。CustomEvent を使用するとコンポーネントは確実にカバーされます。Internet Explorer では CustomEvent インターフェースはネイティブでサポートされませんが、Lightning Web コンポーネントモデルによってそのサポートが追加されます。
Lightning Web コンポーネントには、コンポーネントがイベントを起動できることを登録する、Aura コンポーネントマークアップの <aura:registerEvent> タグに相当するものがありません。標準 DOM イベントを使用するおかげで、この追加の処理は必要ありません。
Aura コンポーネントの event.fire() の代わりに、Lightning Web コンポーネントでは this.dispatchEvent(myEvent) 標準 DOM メソッドを使用します。
以下は、propertyTile Lightning Web コンポーネントでイベントを作成およびディスパッチ (起動) する例です。
export default class PropertyTile extends LightningElement { @api property; propertySelected() { const selectedEvent = new CustomEvent('selected', { detail: this.property.Id, }); this.dispatchEvent(selectedEvent); } }
CustomEvent() コンストラクターの最初の引数は、イベントの名前を selected に設定します。
2 番目の引数は、イベント動作を設定するオブジェクトです。このオブジェクトでは、detail を設定します。これはイベントのデータペイロードです。処理コンポーネントはデータを読み取ることができます。この場合は this.property.Id 値を渡します。
イベントの処理
Aura コンポーネントでは、マークアップで <aura:handler> タグを使用してハンドラーを定義します。もしくは、コンポーネントはマークアップで別のコンポーネントを参照するときにハンドラーアクションを宣言できます。
この Aura コンポーネントは、マークアップで c:child を使用し、c:child が起動する通知イベントの handleNotification ハンドラーを宣言します。
<c:child notification="{!c.handleNotification}"/>
Lightning Web コンポーネントでは、類似の宣言型ハンドラーを使用できます。宣言型ハンドラーのイベント名には、on というプレフィックスが付きます。
<c-child onnotification={handleNotification}></c-child>
handleNotification イベントハンドラー関数は、コンポーネントの JavaScript ファイルで定義されます。
Lightning Web コンポーネントの場合は、コンポーネントの JavaScript ファイルで addEventListener() 標準メソッドを使用してプログラムでハンドラーを設定することもできます。
DreamHouse アプリケーションでは、propertyTile Lightning Web コンポーネントで作成、ディスパッチされる selected イベントがどのように処理されるのか見てみましょう。propertyTileList Lightning Web コンポーネントは、HTML ファイルでこのイベントを処理します。
<template for:each={properties} for:item="property"> <c-property-tile property={property} key={property.Id} onselected={onPropertySelected}></c-property-tile> </template>
selected イベント名には、onselected={onPropertySelected} で設定した宣言型ハンドラーで on というプレフィックスが付きます。
onPropertySelected イベントハンドラー関数は propertyTileList.js で定義されます。
onPropertySelected(event) { pubsub.fire('propertySelected', event.detail); }
selected イベントを propertyTile で起動したときを思い出してください。CustomEvent() コンストラクターで detail が this.property.Id に設定されました。ハンドラーは、event.detail にアクセスしてイベントデータをアンパックします。この例では、event.detail のプロパティ ID を取得します。
次は、アプリケーションイベントを見て、pubsub.fire() で何が起こっているのか説明します。
アプリケーションイベントは Publish-Subscribe パターンになる
Aura コンポーネントのアプリケーションイベントを Lightning Web コンポーネントの pub-sub (publish-subscribe) パターンに移行します。pub-sub パターンでは、あるコンポーネントがイベントを公開し、他のコンポーネントは登録してそのイベントを受信し、処理します。イベントに登録しているすべてのコンポーネントがイベントを受信します。
標準 DOM イベントはコンテインメント階層の上位にのみ伝播していくので、標準 DOM イベントを常に第 1 に選択します。そうすると動作が予測しやすくなります。どのコンポーネントもイベントを処理できるので、複雑なアプリケーションではアプリケーションイベントが問題になることがあります。このパターンは、コンポーネントの予期しない結合により、コードがメンテナンスしにくいものになる可能性があります。ただし、通信するためにコンテインメント階層内の兄弟コンポーネントが必要になる場合があります。Lightning ページや Lightning アプリケーションビルダーで使用される関連しないコンポーネントは、通信する必要がある兄弟コンポーネントの一例です。このようなシナリオでは、pub-sub パターンが適しています。
DreamHouse アプリケーションでは、pubsub.js モジュールが使用されます。pubsub モジュールを自由にコピーして、コードで使用してください。
pubsub モジュールは 3 つのメソッドをエクスポートします。
register: イベントのコールバックを登録します。unregister: イベントのコールバックを登録解除します。fire: イベントをリスナーに対して起動します。囲んでいる Aura コンポーネントへのイベントの送信
Lightning Web コンポーネントは DOM イベントをディスパッチします。囲んでいる Lightning Web コンポーネントと同様に、囲んでいる Aura コンポーネントはこれらのイベントをリスンできます。囲んでいる Aura コンポーネントは、イベントをキャプチャして処理できます。必要に応じて、Aura コンポーネントは Aura イベントを起動し、他の Aura コンポーネントやアプリケーションコンテナと通信できます。
この手法は、Aura コンポーネントでサポートされているけれども、Lightning Web コンポーネントでは現在サポートされていないイベントまたはインターフェースをサポートする場合に役立ちます。
次の例は、この手法を示しています。この Lightning Web コンポーネントは JavaScript ファイルでカスタム notification カスタムイベントを起動します。
// catchAndRelease.js import { LightningElement } from 'lwc'; export default class CatchAndRelease extends LightningElement { /** * Handler for 'Fire My Toast' button. * @param {Event} evt click event. */ handleFireMyToast(evt) { const eventName = 'notification'; const event = new CustomEvent(eventName, { detail: { message: 'See you on the other side.' } }); this.dispatchEvent(event); } }
囲んでいる Aura コンポーネントのラッパーはカスタムイベントにハンドラーを追加します。onnotification イベントハンドラーは on のプレフィックスが付いたイベント名と一致します。つまり、onnotification を使用して、notification という名前のイベントを処理します。
<!-- catchAndReleaseWrapper.cmp --> <aura:component implements="force:appHostable"> <c:catchAndRelease onnotification="{!c.handleCustomEvent}"/> </aura:component>
catchAndReleaseWrapper Aura コンポーネントのコントローラーの handleCustomEvent 関数がイベントを処理します。
// catchAndReleaseWrapperController.js ({ handleCustomEvent: function(cmp, evt) { // Get details from the DOM event fired by the Lightning web component var msg = evt.getParam('message') || ''; } })
Lightning Web コンポーネントによってディスパッチされた通知イベントがイベントの詳細を設定します。
detail: { message: 'See you on the other side.' }
イベントを処理する Aura コンポーネントが evt.getParam('message') を使用してイベントデータにアクセスします。
イベントは好きなように処理できます。必要に応じて、新しい Aura イベントを起動して他の Aura コンポーネントと通信することもできます。
リソース
- Lightning Aura コンポーネント開発者ガイド: イベントとの通信
- Lightning Web Components Developer Guide (Lightning Web コンポーネント開発者ガイド): Migrate Events (イベントの移行)
まとめ
多数の概念を説明しましたが、Aura コンポーネントが Lightning Web コンポーネントにどのようにマッピングされるのかについて理解が深まったことでしょう。さらに詳しく学ぶ一番の方法は、コードでいろいろと試してみることです。次のステップのアイデアをいくつか紹介します。
- DreamHouse アプリケーションコードを調べ、すべてのコンポーネントがどのように連携しているのかを確認する。
- GitHub の lwc-recipes リポジトリで、一般的なユースケース向けの多数のコードサンプルを参照する。
- Sample Gallery (サンプルギャラリー) のサンプルアプリケーションを参照する。
途中で何度かつまずいたり、予想外の脱線があったりしたとしても、ジャーニーをぜひ楽しんでください。
でもこういう場合は?
残念ながら、1 つの Trailhead モジュールで説明できる内容量には限りがあります。モジュールは、水が入ったバケツのようなものです。入れられる水の量は限られており、それを超えると溢れ出します。より大きなバケツを選ぶと、重過ぎて持ち運べなくなります。
知りたい機能の説明がなかった場合、それは説明したくなかったということではありません。バケツがいっぱいなだけです。
コンポーネントのテスト
特に、コンポーネントのテストという重要な部分については説明しませんでした。開発者ガイドで詳細を参照するためのアドバイスは次のとおりです。
Aura コンポーネントでは、Lightning Testing Service を使用してコンポーネントをテストします。
Lightning Web コンポーネントでは、単体テスト用の Jest を使用します。Jest ですべてのテストケースをテストできなければ、Lightning Testing Service を使用して残りのテストケースをテストしてください。「Test Lightning Web Components (Lightning Web コンポーネントのテスト)」を参照してください。
Aura メソッドは JavaScript メソッドになる
Aura コンポーネントの <aura:method> タグのメソッドを、Lightning Web コンポーネントの @api デコレーターを使用する JavaScript メソッドに移行します。
JavaScript メソッドは、コンテインメント階層で下位と通信するために使用します。たとえば、親コンポーネントは、含まれている子コンポーネントのメソッドをコールします。メソッドはコンポーネントの API の一部です。
詳細は、『Lightning Web Components Developer Guide (Lightning Web コンポーネント開発者ガイド)』の「Call Methods on Child Components (子コンポーネントのメソッドのコール)」を参照してください。
インターフェースの移行
Aura コンポーネントのインターフェースは、主にマーカーインターフェースとして使用され、アプリケーションのコンポーネントの特定の使用方法を有効にします。マーカーインターフェースは、属性、イベント、メソッドを含まない空のインターフェースです。
Lightning Web コンポーネントでは、使用方法はコンポーネントの設定ファイルか、簡単な @api デコレーターを使用して定義されます。
詳細は、『Lightning Web Components Developer Guide (Lightning Web コンポーネント開発者ガイド)』の「Migrate Interfaces (インターフェースの移行)」を参照してください。
アクセス制御の移行
Aura バンドルのリソース (コンポーネントや属性など) へのアクセスを管理するには、access システム属性を使用します。
Lightning Web コンポーネントではアクセス制御のメカニズムが異なります。アクセスは、JavaScript プロパティデコレーターとコンポーネントの設定ファイルで定義されます。
詳細は、『Lightning Web Components Developer Guide (Lightning Web コンポーネント開発者ガイド)』の「Migrate Access Controls (アクセス制御の移行)」を参照してください。