【JavaScript】eventとは?イベントの仕組み・使い方を初心者向けにわかりやすく解説

はじめに

JavaScriptでは、ユーザーの操作やブラウザの状態変化などを捉えるための仕組みとしてイベントというものが用意されています。
たとえばボタンをクリックしたとき、キーボードを押下したとき、ページの読み込みが完了したときなど、あらゆるタイミングでイベントは発生します。

このイベントを的確に捉え、そこに適切な処理を結び付けることができると、インタラクティブで扱いやすいWebアプリケーションが作れます。
さらに、実務の現場ではユーザーの反応を素早くキャッチして必要な処理を行うことが求められるため、JavaScriptイベントを理解することはWeb開発者にとって必須のスキルといえるでしょう。

イベントにはさまざまな種類があります。
クリックやホバー、ドラッグ&ドロップ、キーボード入力など、それぞれ役割や使い方も異なりますが、基本の考え方は共通しています。
本記事では、初心者の皆さんにも理解しやすいように、JavaScriptイベントの基礎知識から具体的なコード例まで、丁寧に解説していきます。

イベントの使い方を覚えると、思い通りのタイミングで処理を発動できるようになります。
結果的に、UIが分かりやすくなったり、操作感が向上したりといった恩恵が生まれます。
ではさっそく、イベントの世界を深掘りしていきましょう。

この記事を読むとわかること

  • JavaScriptにおけるイベントの基本的な流れ
  • addEventListenerを使ったイベントリスナーの設定方法
  • イベントフロー (キャプチャリングとバブリング) の考え方
  • イベントオブジェクトの役割や活用例
  • よく使われるイベントの具体的なコード例
  • イベントデリゲーションのメリットと実装例

イベントとは何か?

JavaScriptにおけるイベントとは、ブラウザやユーザーアクションによって発生する「出来事」のようなものです。
ページの読み込み、ユーザーがボタンをクリック、テキストを入力、画面をスクロールといった一連の操作すべてがイベントの対象になります。

たとえば、SNSの投稿ボタンをクリックすると投稿が完了したり、入力フォームでEnterキーを押したタイミングでデータの送信処理が実行されたり。
こういった機能が成り立つのは、イベントを正しく扱っているからです。

イベントの基本的な流れ

  1. 何らかのトリガー (動作) が起こる

    • クリックやキーボード操作など、ユーザーが行う場合もあれば、ブラウザの内部処理による場合もあります。
  2. イベントが発生する

    • ボタンがクリックされた場合であれば“click”というイベントが発生します。
    • ページ読み込みであれば“DOMContentLoaded”や“load”といったイベントが発生します。
  3. イベントリスナーが実行される

    • イベントが発生した要素に結び付けた処理(関数)が呼び出されます。
    • ここで必要なアクション(画面を更新、データ送信など)を行うことができます。

よく使われるイベントの種類

初心者の皆さんがまず覚えておくと便利なイベントの種類をいくつか見ておきましょう。

click

ボタンや画像などがクリックされたときに発生します。
最もよく使われるイベントのひとつです。

keydown / keyup

キーボードのキーが押される、または離されたタイミングで発生します。
ショートカットキーの実装などに使われることが多いです。

submit

フォームが送信されるときに発生します。
入力内容のバリデーション(入力チェック)などに活用できます。

DOMContentLoaded

HTML文書が読み込まれ、DOMツリー(ページ内の要素構造)が構築された段階で発生します。
画面要素に関する処理を行いたい場合に便利です。

これら以外にもマウスを動かすと発生するmousemoveや、要素にカーソルが乗ったときに発生するmouseoverなど、多数のイベントがあります。

実務で活かせるシーン

イベントの知識は、実際の開発や業務で次のようなシーンで役立ちます。

UIの向上

ボタンやリンクなどの操作を素早くキャッチして、リアルタイムに画面を更新できます。

入力フォームの制御

不正な値が入力される前に警告を出す、Enterキーの押下をトリガーにサーバーへ送信するなど、多彩な動きが可能です。

動的なコンテンツ読み込み

ページの一部がスクロールされたタイミングで追加の情報を読み込む仕組みは、イベントをトリガーに実行されることが多いです。

このようにイベントは、ユーザーの操作に合わせて動的に対応できる仕組みをつくる上で欠かせない要素といえます。

イベントリスナーの書き方

JavaScriptでイベントを扱う場合、真っ先に覚えておきたいのがイベントリスナーの設定方法です。
イベントリスナーとは、発生したイベントを捉えて何らかの処理を実行するための仕組みで、addEventListenerというメソッドを使うのが代表的なやり方です。

addEventListenerの基本的な使い方

addEventListenerは、次のように使用します。

// あるDOM要素を取得した上で
const button = document.getElementById("myButton");

// イベントタイプと、実行したい処理をセット
button.addEventListener("click", function() {
  console.log("ボタンがクリックされました!");
});
  • 第一引数: イベントの種類("click"など)
  • 第二引数: 実行するコールバック関数

こうすることで、指定した要素にクリックが起きたとき、コールバック関数内の処理が呼び出されるようになります。

実装例

もう少し具体的な例を見てみましょう。
ボタンをクリックすると、画面上にアラートを表示するコードです。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>ボタンクリック例</title>
  </head>
  <body>
    <button id="myButton">クリックしてみよう</button>

    <script>
      const button = document.getElementById("myButton");

      button.addEventListener("click", function() {
        alert("イベントリスナーが反応しました!");
      });
    </script>
  </body>
</html>

ユーザーがボタンをクリックした瞬間に“click”イベントが発生し、アラートが表示されます。
これは最も単純なサンプルですが、基本的な構造は変わりません。

イベントリスナーを解除するには

removeEventListenerを使うことで、設定したイベントリスナーを解除できます。
たとえば、特定のタイミングで「もうイベントは不要だ」と判断した場合、以下のように書きます。

button.removeEventListener("click", handleClick);

ただしremoveEventListenerを使う場合は、解除対象となるコールバック関数を名前付きで用意しておく必要があります。
無名関数(アロー関数やfunctionの匿名定義)で設定したリスナーは一致しないので注意しましょう。

実装例

以下は、クリックするとイベントリスナーを解除する例です。
初回のクリックだけ反応し、2回目以降は何も起きません。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>イベント解除例</title>
  </head>
  <body>
    <button id="onceButton">一度だけクリック可</button>

    <script>
      const button = document.getElementById("onceButton");

      function handleClick() {
        alert("最初だけ表示されます。");
        button.removeEventListener("click", handleClick);
      }

      button.addEventListener("click", handleClick);
    </script>
  </body>
</html>

「一度だけボタンがクリックされたら処理を実行し、すぐにリスナーを取り外す」というような動きは、ユーザー体験を制御する上で便利です。

イベントフローとは?

JavaScriptのイベントにはイベントフローという考え方があり、これを理解しておくと、複雑なDOM構造でも意図通りにイベントを活用しやすくなります。
イベントフローには、大きく分けて次の2つのフェーズが存在します。

1. キャプチャリングフェーズ

親要素から子要素へ向かってイベントを伝播させるプロセスです。
たとえば、HTMLのルート要素から実際にクリックされた要素まで、順番にイベントが「降りてくる」イメージです。

2. バブリングフェーズ

クリックされた(または何らかの操作が行われた)要素から、再び親要素へ向かってイベントが「泡のように」伝わっていくプロセスです。
これにより、親要素でも同じイベントを扱うことができます。

キャプチャリングとバブリング

要素の階層構造が深い場合、ユーザーがクリックした要素だけでなく、その親要素でも同じクリックイベントを捉えることができます。
これが実務でどのように役立つかというと、たとえば複数の子要素に同じ処理を設定したい場合に、親要素でイベントをまとめて処理するというやり方が考えられます。

一方で、親要素のイベント処理を先に実行したい(キャプチャリング重視)場合などは、addEventListenerの第三引数にtrueを指定するとキャプチャリングフェーズで実行されるようになります。
ただ、初心者の皆さんがいきなりキャプチャリングを多用するケースは少なく、基本的にはバブリングで処理することが多いでしょう。

イベントの伝播を止める方法

意図しない場所でイベントが発火しないようにしたい場合、イベントの伝播を停止させることができます。
よく使われるのはevent.stopPropagation()です。
このメソッドを呼び出すと、それ以降のバブリングやキャプチャリングが行われなくなります。

element.addEventListener("click", function(event) {
  // ここで処理したい内容
  event.stopPropagation();
});

また、event.preventDefault()はフォーム送信やリンクの遷移など、ブラウザがデフォルトで行うアクションを止めるために使われます。
これらのメソッドを効果的に使うと、予期しない画面遷移やイベントの多重発火を防ぐことが可能になります。

イベントオブジェクトの活用方法

JavaScriptのイベントが発生すると、自動的にイベントオブジェクトが生成されます。
このオブジェクトは、イベントに関するさまざまな情報を内包しており、イベントリスナーのコールバック関数の第一引数として受け取ることができます。

button.addEventListener("click", function(e) {
  // eがイベントオブジェクト
  console.log(e.type); // イベントの種類(clickなど)
  console.log(e.target); // イベントが発生した要素
});

イベントオブジェクトで得られる情報

イベントオブジェクトから取得できる主な情報には、以下のようなものがあります。

type

イベントの種類(click、keydownなど)が文字列で入っています。

target

イベントが起きたDOM要素を表します。
たとえばクリックされたボタン要素など。

currentTarget

リスナーをバインドしているDOM要素を示します。
イベントフローの途中で“どの要素のリスナーが処理を実行しているか”を把握するのに役立ちます。

preventDefault()

デフォルトのブラウザ挙動をキャンセルします。
例として、submitイベント時のページリロードを止めたい場合に使われます。

stopPropagation()

先ほど説明した通り、イベントの伝播をストップします。

実務でよく使うプロパティ

実務の観点では、たとえばクリックイベント時のマウス座標情報を取得できるclientXclientYなども使われることがあります。
ドラッグ操作やゲーム開発などで座標管理が必要なときは重宝するでしょう。
また、キーボードイベントの場合は押したキーを表すkeyというプロパティがあり、たとえば「Enter」キーのみを検出して処理を分岐するなどの使い方ができます。

このようにイベントオブジェクトを上手に利用すると、より細かい制御が可能になります。
ひとつひとつを丁寧に把握しておくことで、コードの安定感や表現力がぐっと高まります。

実務でよく使われるイベントの活用例

ここまででイベントの概念や基本的な使い方を説明してきました。
ここからは、実務でも頻繁に利用される代表的なイベントについて、具体的なコード例を交えながら取り上げていきます。

クリックイベント

clickイベントは、Webページの中でもっとも使われるといっても過言ではありません。
ボタン、リンク、画像などをクリックした瞬間に発生するため、多岐にわたる用途があります。

コード例

次の例では、複数のボタンをまとめて処理することで、コードの重複を減らしています。
ユーザーがどのボタンを押したかによって、違ったメッセージを表示できる点がポイントです。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>クリックイベントの例</title>
  </head>
  <body>
    <button class="action-button" data-type="like">いいね</button>
    <button class="action-button" data-type="share">シェア</button>
    <button class="action-button" data-type="comment">コメント</button>

    <script>
      const buttons = document.querySelectorAll(".action-button");

      buttons.forEach(button => {
        button.addEventListener("click", function(e) {
          const actionType = e.target.dataset.type;
          if (actionType === "like") {
            alert("「いいね」がクリックされました。");
          } else if (actionType === "share") {
            alert("「シェア」がクリックされました。");
          } else if (actionType === "comment") {
            alert("「コメント」がクリックされました。");
          }
        });
      });
    </script>
  </body>
</html>

ポイントとしては、HTML上でdata-type属性を使ってボタンごとの区別をしています。
このように属性値を基準にして処理を切り替えると、HTMLとJavaScriptのコードを簡潔に分けやすくなるでしょう。

キーボードイベント

キーボード入力に応じて処理を行う場合は、keydownkeyupイベントが使われます。
たとえばEnterキーだけを捉えたい、特定のショートカットキー操作を捉えたい、といったケースで活躍します。

コード例

以下は、入力欄にフォーカスがある状態でEnterキーが押されたらテキストをコンソールに表示する例です。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>キーボードイベントの例</title>
  </head>
  <body>
    <input type="text" id="textInput" placeholder="ここに文字を入力してEnterを押してください" />

    <script>
      const inputField = document.getElementById("textInput");

      inputField.addEventListener("keydown", function(e) {
        if (e.key === "Enter") {
          console.log("入力された文字:", inputField.value);
        }
      });
    </script>
  </body>
</html>

実務では、チャットアプリでEnterキー送信を実装したり、特定のショートカットキーを押すとツールバーを表示したりなど、多彩な使い方が考えられます。

フォーム送信イベント

フォームを送信するときには、submitイベントを活用します。
フォームが送信される瞬間に入力内容をチェックしたり、画面遷移を制御して非同期でデータ送信したりするときに利用されます。

コード例

以下の例では、入力内容が空だった場合に送信処理を止め、エラーメッセージを表示する仕組みを示しています。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>フォーム送信イベントの例</title>
  </head>
  <body>
    <form id="myForm">
      <input type="text" id="userName" placeholder="ユーザー名" />
      <button type="submit">送信</button>
    </form>

    <script>
      const form = document.getElementById("myForm");
      const userName = document.getElementById("userName");

      form.addEventListener("submit", function(e) {
        if (!userName.value) {
          e.preventDefault(); // 送信処理をキャンセル
          alert("ユーザー名を入力してください。");
          return;
        }

        alert("フォームが送信されました。");
      });
    </script>
  </body>
</html>

ユーザー名が空の場合はpreventDefault()で送信を中断し、アラートを表示しています。
このようにsubmitイベントをフックすることで、実務でも必須の入力チェック送信前の一時保存処理などを簡単に実装できるのです。

DOMContentLoaded

DOMContentLoadedは、HTMLがすべて読み込まれ、DOMツリーが構築された時点で発生するイベントです。
画像やCSSなどの外部リソースを待たずに発火するため、ページの要素を操作したい場合にタイミングが取りやすいという特徴があります。

コード例

以下の例では、ページのDOM構造が完全に読み込まれた後に見出しの文字色を変える実装です。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>DOMContentLoadedの例</title>
  </head>
  <body>
    <h1 id="title">ページ読み込みテスト</h1>

    <script>
      document.addEventListener("DOMContentLoaded", function() {
        const title = document.getElementById("title");
        title.style.color = "red";
      });
    </script>
  </body>
</html>

ここではtitle要素の色を変更していますが、もっと複雑なDOM操作や初期化処理を行うことも可能です。
このイベントを使うと、スクリプトを配置する場所にあまり依存せず、DOM操作のタイミングを管理しやすくなります。

イベントデリゲーションとは?

イベントデリゲーションとは、子要素に個別にイベントリスナーを付与するのではなく、親要素でまとめてイベントを管理する方法です。
大きなメリットとしては、動的に追加される子要素にも対応しやすいという点が挙げられます。

イベントデリゲーションのメリット

DOM操作の負荷削減

子要素一つひとつにイベントリスナーを付与すると、その数だけリスナーが増えていきます。
イベントデリゲーションを使えば、親要素のリスナーをひとつ用意するだけで済むため、コードの簡潔化やパフォーマンス向上につながることがあります。

コードの可読性が向上

子要素が増減する機能を持つUIでは、追加・削除のたびにリスナーを設定したり解除したりする処理を挟むのは煩雑です。
親要素のリスナーで一括管理すれば、そのあたりの処理がシンプルになります。

コード例

以下は、リスト項目をクリックしたときに、どの項目がクリックされたかを判定する例です。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>イベントデリゲーション例</title>
  </head>
  <body>
    <ul id="itemList">
      <li data-item="りんご">りんご</li>
      <li data-item="みかん">みかん</li>
      <li data-item="ぶどう">ぶどう</li>
    </ul>
    <button id="addItem">項目追加</button>

    <script>
      const itemList = document.getElementById("itemList");
      const addItem = document.getElementById("addItem");

      // 親要素であるULにイベントリスナーを設定
      itemList.addEventListener("click", function(e) {
        const clickedItem = e.target;
        // li要素かどうかをチェック
        if (clickedItem.tagName === "LI") {
          alert(clickedItem.dataset.item + "がクリックされました。");
        }
      });

      // 新しい項目を追加するボタン
      addItem.addEventListener("click", function() {
        const newLi = document.createElement("li");
        newLi.textContent = "もも";
        newLi.dataset.item = "もも";
        itemList.appendChild(newLi);
      });
    </script>
  </body>
</html>
  • <ul>にだけイベントリスナーを仕込んでおき、クリックされた要素がLIであれば処理を実行しています。
  • 項目が新たに追加されても、すでに存在するULのイベントリスナーがそれをキャッチできるのがポイントです。

イベントデリゲーションを使うことで、たとえば途中でリストを増やしてもリスナーを改めて指定する必要がなく、保守性や拡張性が高まります。

複雑な画面において、部分的に要素が動的に増える場合は、イベントデリゲーションが非常に便利です。

まとめ

ここまで、JavaScriptのイベントに関する基礎から実装例までを幅広く見てきました。
イベントを扱えるようになると、ユーザーが行う操作を即座にキャッチし、目的に応じた処理を加えることが可能になります。

イベントリスナーの設定

addEventListenerを用いて、クリックやキーボード、フォーム送信など、あらゆるタイミングで処理を実行できます。

イベントフローの理解

キャプチャリングとバブリングを把握することで、意図しない箇所でイベントが発火するのを防ぎ、または逆に親要素側でまとめて処理することもできます。

イベントオブジェクトの活用

イベントの種類や座標、キー情報など、細かい制御が必要な場合に役立ちます。

イベントデリゲーションのメリット

子要素が増減しても、親要素だけでイベントを管理できるため、コードをすっきり保つことができます。

実務の現場でも、イベントの仕組みを知らずに開発を進めるのは難しいでしょう。
たとえばフォームバリデーションや、ユーザーの操作によって画面を動的に更新する機能など、さまざまな場面でイメージがつくはずです。
ぜひ本記事の内容を参考に、アプリケーションをより操作しやすいものへと育ててください。

もちろん、本記事で挙げたイベントの種類は氷山の一角です。
スクロールに関連するイベントや、ドラッグ&ドロップを実現するイベントなど、Webアプリケーションを高度に構築するためには多種多様なイベントへの理解が必要になります。

しかし、まずはクリック、キーボード入力、フォーム送信、そしてDOMの読み込みといった基本的なイベントをしっかりと押さえることで、Web開発の多くの場面をカバーできます。
それらを踏まえ、実務に応じたイベント活用をどんどん試してみると良いでしょう。

今後、Webアプリケーション開発に深く取り組む際は、ユーザー体験を良くするためにイベントの設計が重要になります。
どのタイミングで何を実行し、どの要素がイベントを受け取るのかを明確にすることで、保守性も高いコードを書くことが可能です。

イベントを正しく理解し、有効に活用することで、Webページはただの静的なコンテンツから、ユーザーとの対話が可能な生きたアプリケーションへと変貌します。
ぜひ今回の知識を活かして、より魅力的で使いやすいWebサービスを生み出してみてください。

JavaScriptをマスターしよう

この記事で学んだJavaScriptの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。