イベントの処理

イベントをリスンするには、コンポーネントの HTML テンプレートから宣言的に行う方法と、命令 JavaScript API を使用してプログラムで行う方法の 2 つがあります。推奨されるのは、HTML テンプレートからリスンする方法です。この方法では、記述する必要があるコード量が削減されるためです。イベントを処理するには、コンポーネントの JavaScript クラスでメソッドを定義します。

オーナーコンポーネント (この例では c-parent) のテンプレートのマークアップでリスナーを宣言します。

ハンドラ関数 (この例では handleNotification) を c-parent の JavaScript ファイルで定義します。

リスナーとハンドラ関数の両方を c-parent の JavaScript で定義します。

同じ要素に同じリスナーが繰り返し追加されると、ブラウザによって重複が無視されます。

イベントリスナーが削除されていない場合、addEventListener() コールに handleNotification コードを埋め込むことができます。

addEventListener({eventName}, this.handleNotification.bind(this)) は使用しないでください。bind() は新しい関数を返すため、コンポーネントは同じ関数インスタンスで removeEventListener() をコールできません。そのため、これはアンチパターンになります。コンポーネントは同じ関数インスタンスを使用できないため、リスナーでメモリリークが発生します。

イベントリスナーを追加するための構文は 2 つあります。片方はコンポーネントのシャドウ境界内の要素にイベントリスナーを追加し、他方はテンプレートが所有しない要素 (例: スロットに渡された要素) にイベントリスナーを追加します。

シャドウ境界内の要素にイベントリスナーを追加するには template を使用します。

テンプレートが所有しない要素にイベントリスナーを追加するには addEventListener を直接コールします。

イベントをディスパッチしたオブジェクトへの参照を取得するには、イベントの DOM API の一部である Event.target プロパティを使用します。

lwc-recipes リポジトリのいくつかのレシピでは、Event.target を使用しています。例を見るには、リポジトリで Event.target を検索してください。

イベントが DOM ツリーを上に伝達するときにシャドウ境界を越えると、Event.target の値がリスナーの範囲に合わせて変更されます。この変更は「イベントの対象変更」と呼ばれます。イベントの対象が変更されるため、リスナーはイベントをディスパッチしたコンポーネントの Shadow DOM ツリーを見ることができません。イベントの対象が変更されても、Shadow DOM のカプセル化は維持されます。

簡単な例を見てみましょう。

<my-button> に対するクリックリスナーは、クリックが button 要素に対して発生した場合でも、常に my-button を対象として受け取ります。

c-todo-item コンポーネントの div 要素からイベントがディスパッチされたと想定します。コンポーネントの Shadow DOM 内では Event.targetdiv です。ただし、c-todo-app コンポーネント内の p 要素のリスナーにとっては Event.targetc-todo-item です。これは、p 要素は c-todo-item Shadow DOM を調べることができないためです。

興味深いことに、c-todo-item 上のリスナーにとっても、c-todo-item がシャドウ境界の外部に存在するため、Event.targetdiv ではなく c-todo-item になります。

テキスト項目 (<input> または <lightning-input>) など、入力を受け入れるテンプレート内の要素からの変更をリスンするには onchange イベントを使用します。

次の例では、入力の値が変更されるたびに、JavaScript ファイル内の handleChange() メソッドが呼び出されます。

myValue プロパティは、入力要素の値を表します。この_プロパティ_値は、変更が発生するたびに自動的には更新されません。

値を自動修正したり制限したりするために、ユーザが入力した値を検証したい場合があります。myValue を現在の入力値と同期させるには、handleChange() メソッドで myValue を更新します。次の例では、文字列の先頭と末尾から空白スペースを削除することで、入力された値を自動修正しています。入力項目の現在値を取得するには、evt.target.value を使用します。

次の例では、evt.target.value = trimmedValue の行で入力値プロパティを切り取り後の値にリセットする方法を示しています。また、今後コンポーネントがリハイドレートされた (新しい値が読み込まれた) 場合でも myValue プロパティの値を正規化された値と同期させる方法も示しています。

テンプレートで定義された要素からのプロパティを変更すると、コンポーネント以外の場所で望まない副作用をもたらすことがあります。上の例では、要素の入力値プロパティは、テンプレートで定義されている値 (evt.target) から変更されています。また、テンプレートで使用されている値 (myValue) を変更して、コンポーネント要素の状態を同期させています。こうしないと、テンプレートのリハイドレーションで要素の状態とコンポーネントの状態を合わせようとしたときにプロパティ値の不一致が検出されます。この不一致によってランタイムの警告が発生するため、コンポーネントまたは JavaScript を適合させてテンプレートのデータ整合性を維持する必要があります。

リスナーの管理とクリーンアップは、コンポーネントライフサイクルの一環としてフレームワークが担当します。ただし、リスナーを他のオブジェクト (window オブジェクトや document オブジェクトなど) に追加する場合は、ユーザ自身がリスナーを削除する必要があります。

イベントリスナーを削除するには、disconnectedCallback ライフサイクルフックを使用します。

関連トピック