Skip to content
This page has been auto-translated and may contain errors.View in English

イベント

docs.scrimba.com

反応しないページは単なるドキュメントです。ボタンをクリックしたときに何かが起こるようにしたい、検索ボックスに入力したい、またはフォームを送信したいという瞬間、「これが起こったら、このコードを実行する」と言う方法が必要です。それがイベントです。このチャプターでは、ユーザーが何をするかを聞いて、それに応答することについてです。

イベントをリッスンする

**イベント**とは、ページで起こることです:クリック、キー入力、フォーム送信。それに応答するために、要素を選び、関心のあるイベント名を指定し、それが起こったときに実行する関数を渡します。

その関数をハンドラーと呼びます。それを接続するメソッドはaddEventListenerです:

js
const button = document.querySelector(".buy-button");

button.addEventListener("click", () => {
  console.log("誰かが購入をクリックしました");
});

左から右に読んでください:このボタンで、"click"をリッスンして、それが起こったら、この関数を実行してください。ハンドラーは一度だけでなく、イベントが起こるたびに実行されます。3回クリックすると、3回実行されます。

**イベント**は、何かが起こったときにブラウザーが発火するシグナルです:ユーザーがクリック、入力、フォーム送信、またはページが読み込み完了します。イベント名を文字列として、そして各回発火するときに呼び出す関数を受け取るaddEventListenerでハンドラーを登録して応答します。

js
const button = document.querySelector(".buy-button");

const handleBuy = () => {
  console.log("誰かが購入をクリックしました");
};

button.addEventListener("click", handleBuy);

handleBuyは括弧なしで渡されることに注意してください。あなたは関数自体をブラウザーに後で呼び出させるために渡しており、今それを呼び出しているわけではありません。addEventListener("click", handleBuy())と書くと、それが即座に呼び出され、それが返す内容(何であれ)が登録され、これは初期段階の一般的な間違いです。

**イベント**は、ブラウザーがそれに関心を登録したコードに対して発火するメッセージです。addEventListener(type, handler)で登録します:typeはイベント名を文字列として、handlerはブラウザーがそのイベントがその要素で発火するたびに呼び出すコールバックです。

js
const button = document.querySelector(".buy-button");

const handleBuy = () => {
  console.log("誰かが購入をクリックしました");
};

button.addEventListener("click", handleBuy);

ここで2つのことが重要です。まず、handleBuy()の結果ではなく、関数値であるhandleBuyを渡します。次に、addEventListenerは加法的です:2つの関数で2回呼び出すと、どちらも実行されるため、リスナーは上書きではなくスタックします。これがbutton.onclickを割り当てるのではなく存在する実用的な理由です。button.onclickは単一のハンドラーを保持し、以前のハンドラーを上書きします。後でハンドラーを削除したいときのために、ハンドラーへの名前付き参照を保持することも重要です。

ハンドラーは通常の関数であり、それらを接続する要素はDOMから来ます。要素を選択して関数を書くことができれば、ユーザーがそれに何をするかに応答できます。

Junoイベントをリッスンする ユーザーに応答するために、要素を選び、イベント名を"click"のような文字列として指定し、addEventListenerに実行する関数を与えます。その関数はハンドラーであり、一度だけでなく、イベントが起こるたびに実行されます。このメソッド1つは、ページがあなたに応答してすることのほとんどすべての背後にあります。
JunoイベントをリッスンするaddEventListenerはイベント名と関数を受け取り、イベントが発火するたびにその関数を呼び出します。括弧なしで関数を名前で渡します:handleBuy()ではなくhandleBuy。括弧を追加すると、クリック時ではなく今すぐ呼び出され、これはほぼ誰もが一度引っかかります。
JunoイベントをリッスンするaddEventListenerはブラウザーが各一致するイベントで発火するコールバックを登録し、上書きではなくスタックします。これがonclickより好まれる理由です。関数値を渡し、その呼び出し結果ではありません。つまりhandleBuyであり、決してhandleBuy()ではありません。リスナーを削除する時期が来たときのために、名前付き参照も保持してください。

イベントオブジェクト

ブラウザーがハンドラーを実行するとき、1つの情報を渡します:何が起こったかを説明する**イベントオブジェクト**。通常eventという名前のパラメーターを与えてハンドラーでキャッチします:

js
const button = document.querySelector(".buy-button");

button.addEventListener("click", (event) => {
  console.log(event.target); // クリックされた要素
});

最も便利な部分はevent.target:イベントが起こった要素。ボタンをクリックした場合、event.targetがそのボタンです。再度選択する必要はありません。イベントはすでにどこから来たかを教えています。

すべてのハンドラーは1つの引数を受け取ります:何が起こったかについての詳細を含む**イベントオブジェクト**。パラメーターに名前を付けて(慣例的にはeventまたはe)キャッチします:

js
const search = document.querySelector(".search-input");

search.addEventListener("input", (event) => {
  console.log(event.target.value); // ユーザーがこれまで入力したもの
});

event.targetはイベントが発火した要素です。フォームフィールドでは、event.target.valueは入力の現在のテキストを与えるため、ショーの主役です。その対、inputイベント+event.target.valueは、誰かが入力しながら何を入力しているかを読む方法です。

ブラウザーは1つの引数を渡します:ハンドラーに**イベントオブジェクト**、何が起こったかのスナップショット:どの要素、どのキー、マウスの位置、およびイベントのデフォルト動作を制御するメソッド。パラメーター(慣例的にevent)でキャッチします。

js
const search = document.querySelector(".search-input");

search.addEventListener("input", (event) => {
  console.log(event.target.value); // フィールド内の現在のテキスト
});

event.targetはイベントを開始した要素です。これは常にリスナーを接続した要素ではありません(それはevent.currentTargetであり、それらの間の隔たりはデリゲーションを機能させるものです。下記参照)。フォームコントロールでは、event.target.valueは現在の値を文字列として読み込みます。つまり、HTMLが保持するのと同じ.valueがテキストとしてここに戻ります。数値に到達し、Number(event.target.value)で自分自身で変換します。

Junoイベントオブジェクト ハンドラーは1つの引数であるeventという名前のパラメーターを与えて取得し、イベントオブジェクトを受け取ります。最も到達するのはevent.target、イベントが起こった要素です。再度選択する必要はありません。イベントはすでにどこから来たかを知っています。
Junoイベントオブジェクトeventという名前のパラメーターを付け、ブラウザーは何が起こったかについての詳細で埋めます。event.targetはそれが発火した要素で、入力ではevent.target.valueはフィールド内の現在のテキストです。inputイベントをevent.target.valueとペアにして、誰かが入力しながら何を入力しているかを読むことができます。
Junoイベントオブジェクト イベントオブジェクトは何が起こったかのスナップショットであり、event.targetはそれが始まった場所です。これは常にリスナーを接続した場所ではありません;それはevent.currentTargetです。フォームフィールドでevent.target.valueは文字列として戻り、数値が必要な場合はNumber(...)で包みます。targetとcurrentTargetの分割をデリゲーションが依存しているため、念頭に置いてください。

一般的なイベント

少数のイベントがあなたが構築する大部分をカバーします:

  • click:ユーザーが何かをクリックまたはタップします。
  • input:テキストフィールドの値が入力時に変わります。
  • submit:フォームが送信されます。
  • keydown:キーが押されます。

厄介なのはsubmitです。デフォルトでは、フォームを送信するとページがリロードされ、JavaScriptが行っていたことがすべて消えます。それを止めるには、ハンドラー内でevent.preventDefault()を呼び出します:

js
const form = document.querySelector("form");

form.addEventListener("submit", (event) => {
  event.preventDefault(); // ページがリロードするのを止める
  console.log("フォームが送信されました、ページはそのままです");
});

ほとんどのページは、イベントの小さなセットに依存しています:ボタンのclick、テキストフィールドが変わるときのinput、フォームのsubmit、キーボードショートカットのkeydown。この4つを学べば、相互作用の大部分を構築できます。

人々を引っかかるのはsubmitです。フォームのデフォルト動作はページをリロードするか、ナビゲートします。これはあなたのコードが処理していたことを削除します。event.preventDefault()を呼び出してページをそのままにし、自分自身で引き継ぎます:

js
const form = document.querySelector("form");

const handleSubmit = (event) => {
  event.preventDefault();
  const email = form.querySelector(".email-input").value;
  console.log(`${email}でサインアップしています`);
};

form.addEventListener("submit", handleSubmit);

ボタンでclickをではなく、フォーム自体でsubmitをリッスンしてください。これにより、Enterキーを押すキーボードユーザーもカバーされます。

4つのイベントが大部分のインタラクションを運びます:clickinput(すべての値の変更で発火し、changeはぼかすのを待つのと異なり)、submit、およびkeydown。それらを正しい要素にバインドすれば、ほとんどのUIはそれらから落ちます。

submitイベントはpreventDefaultが場所を稼ぐ場所です。フォームのデフォルトアクションは完全なナビゲーションであり、ページ内の状態を破棄します。event.preventDefault()を呼び出すことでそれをキャンセルしてデータ自身を処理します:

js
const form = document.querySelector("form");

const handleSubmit = (event) => {
  event.preventDefault();
  const email = form.querySelector(".email-input").value;
  console.log(`${email}でサインアップしています`);
  // それをサーバーに送信することは次のチャプターの仕事です
};

form.addEventListener("submit", handleSubmit);

ボタンのclickではなく、フォームのsubmitに接続してください:submitはEnterキー、ボタンのクリック、およびプログラムによる送信のために発火するため、それは正しいフックです。値を取得したら、それをどこかに送信することはasyncコードが来る場所であり、これは次のチャプターです。

バブリングとデリゲーション

要素をクリックするとき、イベントはそこで止まりません。**バブル**します:クリックされた要素で発火し、その後その親、その後その親の親、すべて上まで。これが親のリスナーが子のクリックを聞く理由です。

その動作はデリゲーションに力を与えます:親に1つのリスナーを接続し、event.targetを使用してどの子が実際にクリックされたかを見つけます。アイテムあたりのリスナーの代わりに、それらすべてをカバーする1つを取得します。

js
const list = document.querySelector(".todo-list");

list.addEventListener("click", (event) => {
  if (event.target.matches(".delete")) {
    event.target.closest("li").remove();
  }
});

見返り:これは後でリストに追加されたアイテムを処理します。アイテムあたりのリスナーは、現在存在する要素にのみバインドされます。親のデリゲートされたリスナーは、イベントがまだリッスンしている親にバブルするため、コードが実行されたときに存在しなかった子のクリックをキャッチします。

リスナーの削除

removeEventListenerはハンドラーをデタッチしますが、追加したのと正確に同じ関数参照を渡す場合のみです:

js
const button = document.querySelector(".buy-button");

button.addEventListener("click", handleBuy);
button.removeEventListener("click", handleBuy); // 機能:同じ参照

これが匿名ハンドラーを削除できない理由です。addEventListener("click", () => {...})のようなインラインアロー関数は、毎回新しい関数を作成するため、removeEventListenerに渡す参照がなく、リスナーは引っかかったままです。削除する予定の名前付きハンドラーはそれを避けます。接触する要素より長く生存するリスナーは、ページが不要な要素のオブジェクトがリスナーがそれを指しているため、回収できないため、実際のメモリリークのソースです。

もう1つのパフォーマンスの注記:スクロールまたはタッチリスナーで3番目の引数として{ passive: true }を追加すると、preventDefaultを呼び出さないことを約束するため、ブラウザーはハンドラーを待たずにスクロールでき、スクロールは滑らかです。

Juno一般的なイベント 最も使用するイベントはclickinputsubmitkeydownです。覚えるのはsubmit:フォームはデフォルトでページをリロードするため、ハンドラーでevent.preventDefault()を呼び出してそれを止めて、制御を保つ。それを見落とすと、ページがあなたから更新されます。これは初めてのときは混乱しています。
Juno一般的なイベントclickinputsubmitkeydownはあなたが構築するものの大部分をカバーします。ボタンでclickではなく、フォームでsubmitをリッスンしてください。キーボードユーザーのためにEnterが機能するようにするため。そして、送信ハンドラーでevent.preventDefault()を呼び出してください。または、ページがリロードされ、あなたの状態を連れて行きます。
Juno一般的なイベント イベントは親にバブルするため、1つのデリゲートされたリスナーとevent.targetが多くの子をカバーし、後で追加されたものも含みます。removeEventListenerは追加したのと同じ関数参照が必要です。これが匿名ハンドラーが削除できず、メモリリークする可能性がある理由です。そしてsubmitはボタンのclickを打ちます。Enterのために発火するため;そこにevent.preventDefault()を保つことでリロードを止めます。

イベントがここから行くところ

イベントはページがリッスンする方法です。要素を選び、何を気にするかに名前を付け、それが起こったときに関数を実行し、進むにつれてイベントオブジェクトから詳細を読みます。ほぼあらゆるインタラクティブ機能はそのループから構築されています。

自然な次のステップは、ハンドラーで遅いことをすることです。フォームをサーバーに送信したり、ページを凍結させずに新しいデータを読み込んだりするなど。これがasyncコードの目的であり、次のチャプターです。オブジェクトに保つアイテムのリストのような構造化されたデータに達するハンドラーも、あなたがすでに知っているものに依存しています。