js におけるイベントバブリングとイベントキャプチャの簡単な分析

js におけるイベントバブリングとイベントキャプチャの簡単な分析

01-イベントバブリング

1.1- イベントバブリングの概要

このセクションの知識ポイント: イベントバブリングとは何かを紹介する

  • イベントバブリング: 要素のイベントがトリガーされると、そのすべての親要素の同じ名前のイベントも順番にトリガーされます。

要素->親要素->本文->html->ドキュメント->ウィンドウ

イベントバブリングは以前から存在していましたが、これまで親要素に同じイベントを追加していませんでした。

<!DOCTYPE html>
<html lang="ja">

<ヘッド>
    <メタ文字セット="UTF-8">
    <meta http-equiv="X-UA-compatible" content="IE=edge">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
    <title>イベントバブリング</title>
    <スタイル>
        。親 {
            位置: 相対的;

            幅: 200ピクセル;
            高さ: 200px;
            背景色: ピンク;
        }

        .息子{
            位置: 絶対;

            左: 400px;
            上: 300px;

            幅: 100ピクセル;
            高さ: 100px;
            背景色: 赤;
        }
    </スタイル>
</head>

<本文>
    <!-- バブル: バブル -->

    <div class="parent">
        <div class="son"></div>
    </div>

    <スクリプト>
        // バブリングを証明する: 親と子に同じタイプのイベントを追加するだけです const parent = document.querySelector('.parent')
        const 息子 = 親.firstElementChild

        // クリックイベントを親と子にバインドします parent.onclick = function () {
            コンソールログ('親')
        }

        // 親要素をクリックすると親が出力され、子要素をクリックすると親も出力されます
        // 1. すべての要素にイベントがあります。イベントが与えられているかどうかに関係なく、すべての要素にイベントがあります。 // 2. 息子をクリックすると、親のクリック イベントがトリガーされます。イベント バブリングが発生します。 // トップレベルのオブジェクト ウィンドウを含むすべての要素にイベントがあります。
        window.onclick = 関数(){
            コンソールログ('ウィンドウ')
        }

        // イベント チェーン: ターゲット要素 -> 親 -> 親 -> 本文 -> HTML -> ドキュメント -> ウィンドウ
        // イベントバブリング: ほとんどの場合役に立たない (そして悪い)
    </スクリプト>
</本文>

</html>

1.2-イベントバブリングの利用(イベント委任)

このセクションの知識ポイント: イベントバブリングの利点を紹介する

​ イベントバブリングの利点:親要素の複数の子要素にイベントを追加したい場合、親要素にイベントを追加するだけで、

イベント ソース (e.target) を取得することで、どの子要素がイベントをトリガーしたかを知ることができます。

<!DOCTYPE html>
<html lang="ja">

<ヘッド>
    <メタ文字セット="UTF-8">
    <meta http-equiv="X-UA-compatible" content="IE=edge">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
    <title>イベントバブリング - アプリケーション - イベント委任</title>
    <スタイル>
        li {
            マージン: 20px 0;
        }
    </スタイル>
</head>

<本文>
    <ul>
        <li>百里守月 1</li>
        <li>百里守月 2</li>
        <li>百里守月 3</li>
    </ul>

    <スクリプト>
        // 要件: すべての li にマウスイン/アウトイベントを追加します。色を変更するだけです。// document.querySelectorAll('li').forEach(function (li) {
        // li.onmouseover = 関数 () {
        // this.style.backgroundColor = '赤'
        // }

        // li.onmouseout = 関数 () {
        // this.style.backgroundColor = ''
        // }
        // })

        // 1. コード実行効率が低い: すべての li を 1 つずつイベントにバインドする必要がある // 2. スケーラビリティが弱い: 新しい li を追加すると無効になる // innerHTML: すべてが無効 // document.querySelector('ul').innerHTML += '<li>innerHTML 的 li</li>'
        // ロジック: ul 内のすべての li (構造、イベントを除く) を取り出し、(文字列形式) に戻します。すべてのイベントが失われます // document.createElement() + appendChild(): 新しいイベントは無効です // let li = document.createElement('li')
        // li.innerHTML = 'li は creatElement によって作成されました'
        // document.querySelector('ul').appendChild(li)

        // イベント委任: 子要素のバインドされたイベント (エフェクト コード) を親要素にバインドします document.querySelector('ul').onmouseover = function (e) {
            // イベント オブジェクトの場合: e.target はイベントをトリガーした元のターゲット (最上位の子) です。
            コンソールログ(e.target)

            // 対象要素が li か ul かを区別するにはどうすればよいでしょうか? ノード: ノードの 3 つの要素 // nodeType: li と ul はどちらも要素で、1
            // nodeValue: li と element は両方とも要素、null
            // nodeName: は要素タグの大文字の名前です: LI UL
            console.log(e.target.nodeName)
            if (e.target.nodeName === 'LI') {
                // ターゲット要素 e.target.style.backgroundColor = 'red'
            }
        }

        document.querySelector('ul').onmouseout = 関数 (e) {
            if (e.target.nodeName === 'LI') {
                // はターゲット要素です e.target.style.backgroundColor = ''
            }
        }

        // 最大の利点: イベントを一度だけバインドする (パフォーマンスが大幅に向上)
        // 二次的な利点: innerHTMl が createElement によって変更または作成されたかどうかに関係なく、すべての li は有効です // document.querySelector('ul').innerHTML += '<li>innerHTML 的 li</li>'
        // これはまさにイベント委譲のためです。将来的に要素を作成する必要がなくなり、innerHTML を直接使用する方がはるかに便利です // let li = document.createElement('li')
        // li.innerHTML = 'li は creatElement によって作成されました'
        // document.querySelector('ul').appendChild(li)

        // イベント委任: イベントバブリングの唯一の値です (非常に便利です)
    </スクリプト>
</本文>

</html>

1.3 イベントバブリングの影響とイベントバブリングの防止

  • このセクションの知識ポイント: イベントバブリングの影響を紹介する

イベントバブリングは要求の衝突を引き起こす可能性があります。たとえば、ログインウィンドウがポップアップした後、ボディの空白領域をクリックしてログインウィンドウを消す機能を追加したいとします。このとき、aタグのポップアップログインウィンドウのクリックイベントがボディのクリックイベントをトリガーし、ログインウィンドウが表示されるとすぐに消えてしまいます。

解決策: イベントのバブリングを防ぐ (次のセクションの知識ポイント)

  • このセクションの知識ポイント: イベントのバブルを防ぐ

イベントのバブリングを防ぐ: 親要素で同じ名前のイベントがバブリング(トリガー)するのを防ぎます

 * 平たく言えば、要素をクリックすると、現在の要素のイベントのみがトリガーされ、同じ名前の親要素のイベントはトリガーされません。

構文: event object.stopPropagation() IE8以前ではサポートされていません

イベントオブジェクト.cancelBubble = true IE8 より前でサポート

注意: イベントのバブリングを防ぎたい場合は、イベントをトリガーする関数でイベントオブジェクトを受け取るようにしてください。

<!DOCTYPE html>
<html lang="ja">

<ヘッド>
    <メタ文字セット="UTF-8">
    <meta http-equiv="X-UA-compatible" content="IE=edge">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
    <title>イベント バブリング - 影響 - イベント バブリングの防止</title>
    <スタイル>
        * {
            マージン: 0;
            パディング: 0;
        }

        {
            テキスト装飾: なし;
            表示: ブロック;

            幅: 200ピクセル;
            マージン: 20px 自動;
        }

        。形状 {
            位置: 相対的;

            幅: 400ピクセル;
            高さ: 200px;
            マージン: 0 自動;
            テキスト配置: 中央;
            境界線: 1px 実線 #ccc;

            表示: なし;
        }

        .form スパン {
            表示: ブロック;
            位置: 絶対;
            右: -25px;
            上: -25px;

            幅: 50px;
            高さ: 50px;
            テキスト配置: 中央;
            行の高さ: 50px;
            境界線: 1px 実線 #ccc;
            境界線の半径: 50%;
            背景色: #fff;
            カーソル: ポインタ;

        }
    </スタイル>
</head>

<本文>
    <a href="javascript:;" rel="external nofollow" >クリックするとログインボックスが表示されます</a>

    <div class="form">
        <span>バツ</span>
        ユーザー名: <input type="text" name="username"><br>
        パスワード: <input type="password" name="password"><br>
        <button>ログイン</button>
    </div>

    <スクリプト>
        // イベントバブリング: 子要素のイベントがトリガーされ、親要素の同じイベントがトリガーされます // 要件: リンクをクリックするとログインボックスが表示され、空白スペースをクリックするとログインボックスが非表示になります const a = document.querySelector('a')
        定数フォーム = document.querySelector('.form')
        定数 x = フォーム.firstElementChild

        // バブリングを停止: イベントの通過を停止: イベント オブジェクト e.stopPropagation()
        // 子要素が親要素に子要素と同じイベントをトリガーさせたくない場合は、子要素のイベントで送信を禁止します // 1. クリックイベントを与える: div.form を表示します
        a.onclick = 関数 (e) {
            コンソールログ('a')
            form.style.display = 'ブロック'

            コンソール.log(e)
            // 送信を防止: イベントをクリックし、e.stopPropagation() で終了
        }

        // 2. 空白部分をクリックして div.form を非表示にします。シンプル: document || window にクリックイベントを与えます。document.onclick = function () {
            console.log('ドキュメント')
            フォーム.スタイル.表示 = ''
        }

        // 3. 安全のため、formdiv 全体をクリック可能にし、form.onclick = function (e) {を渡さないようにします。
            e.stopPropagation()
        }

        // 4. クリックして閉じる x.onclick = function () {
            フォーム.スタイル.表示 = ''
        }

        // まとめ // 実際の開発では、親と子で同じタイプのイベントが発生することがあります。効果が逆の場合 (a は div を表示したいが、document は div を非表示にしたい)、イベントの送信を防ぐために e.stopPropagation() を使用するのが一般的です。
    </スクリプト>
</本文>

</html>

02-イベントキャプチャ

1.1- イベントキャプチャの概要

このセクションの知識ポイント: イベントキャプチャ

  • 1. イベントバブリング: イベントをトリガーする要素から、同じ名前のイベントをトリガーする親要素を1レベルずつ検索し、見つかった場合はトリガーします。
  • 2. イベント キャプチャ: 最上位の親要素から、イベントをトリガーする要素が見つかるまで、一度に 1 レベルずつ下方向に検索して、同じ名前でイベントをトリガーする子要素を探します。

イベントキャプチャとイベントバブリングは、まったく逆の順序でイベントをトリガーします。

  • 3. イベントキャプチャはaddEventListenerを通じてのみ実行でき、パラメータはtrueとして記述されます。

その他はバブリングしています (addEventListener を通じて追加されていない、addEventListener パラメータが false)

  • 4. イベントオブジェクト.stopPropagation()はバブリングを停止するだけでなく、キャプチャも停止します。
  • 5. IE8 以前はキャプチャされません。

1.2-イベントの3つのステージ

このセクションの知識ポイント: イベントの3つの段階を紹介する

  • 1. イベントには3つの段階があります。イベントが実行される順序

1 – キャプチャフェーズ:
2 – ターゲットフェーズ:
3 – 泡立ち段階:

  • 2. イベントオブジェクト.eventPhaseは、このイベントがトリガーされたときのフェーズを取得できます。
  • 3. まず、最上位レベルから下に向かってキャプチャし、次にターゲットをキャプチャし、ターゲットをバブルし、レベルごとにバブルアップします。
<!DOCTYPE html>
<html lang="ja">

<ヘッド>
    <メタ文字セット="UTF-8">
    <meta http-equiv="X-UA-compatible" content="IE=edge">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
    <title>イベントキャプチャ</title>
</head>

<本文>
    <div class="box">私はシャオ・マ・ゲです</div>

    <スクリプト>
        // イベント: すべてバブリングイベントです window.onclick = function () {
            console.log('ウィンドウバブルイベント')
        }

        document.onclick = 関数(){
            console.log('ドキュメントのバブリングイベント')
        }

        const ボックス = document.querySelector('.box')

        box.onclick = 関数(){
            console.log('ボックスのバブルイベント')
        }

        // イベントをキャプチャする: 方法は 1 つだけ addEventListener('event type', callback function, true)
        window.addEventListener('click', 関数() {
            // console.log('ウィンドウキャプチャイベント')
        }、 真実)

        document.addEventListener('クリック', 関数() {
            console.log('ドキュメントキャプチャイベント')
        }、 真実)

        // イベント キャプチャの唯一の価値: イベント ターゲットを準備する // イベント フロー: 最初にキャプチャ、次にターゲット、次にバブル // ターゲット フェーズ: キャプチャとバブルを区別しない (どのコードが前にあり、どちらが最初に実行されるか)
        // 最新の Google: 最初にキャプチャし、次にバブル // IE が順調 (ターゲット フェーズ)

        // ボックスの前にクリックバブルが既にあります box.addEventListener('click', function () {
            console.log('ボックスキャプチャイベント')
        }、 真実)

        // e.stopPropagation() はイベントの配信を整理します。キャプチャフェーズでブロックされると、js のバグが発生します。
        window.addEventListener('click', 関数(e) {
            e.stopPropagation()
        }、 真実)

    </スクリプト>
</本文>

</html>```

js のイベント バブリングとイベント キャプチャの簡単な分析に関するこの記事はこれで終わりです。より関連性の高い js イベント バブリングとイベント キャプチャのコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、次の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • 最もよく使用されるJavaScriptイベントについて詳しく学ぶ
  • JavaScriptのイベントループの仕組みの分析
  • JavaScript イベント キャプチャ バブリングとキャプチャの詳細
  • jsイベント委譲の詳細な説明
  • JavaScript イベント ループのケース スタディ
  • Javascript イベントキャプチャとバブリングメソッドの詳細な説明

<<:  MySQL は制限を使用してページング例メソッドを実装します

>>:  EclipseのプロジェクトをTomcatに追加できない問題を解決する方法

推薦する

Vue ベースの要素ボタン権限実装ソリューション

背景要件: ERP システムに「ボタン権限制御」機能を追加する必要があり、権限の制御粒度をボタン レ...

CentOS での mysql5.7 の詳細なインストールと設定のチュートリアル

インストールユーザーにインストール権限があることを確認してくださいルートスイッチなしsuルート(su...

CSSはカラフルでスマートな影の効果を実現します

背景前景要素から特定の色を継承する影の効果を作成する方法を知りたいと思ったことはありませんか?方法に...

MySQL の列から行への変換と年月グループ化の例

以下のように表示されます。 SELECT count(DISTINCT(a.rect_id)) zc...

ウェブデザイナーが持つべき資質と能力

Web デザインは、インターネットの出現後に誕生した新興の周辺産業です。 Web ページは店頭のよう...

DockerHubイメージリポジトリの使い方の詳しい説明

これまで使用していたイメージはすべて DockerHub パブリック リポジトリから取得していました...

Tomcatのクラスロードメカニズムを説明する記事

目次- 序文 - - JVM クラスローダー - 1. JVMクラスローダー2. クラスローダーのソ...

MySQL sql_modeクエリと設定の詳細な説明

1. SQLを実行して表示する @@session.sql_mode を選択します。 グローバルレベ...

Nginx イントラネット スタンドアロン リバース プロキシの実装

目次1 Nginxのインストール2 Nginxの設定3 ホストファイルを変更する4 テストNginx...

Linux仮想メモリについての簡単な説明

目次起源仮想メモリページングとページテーブルメモリのアドレス指定と割り当て関数プロセスメモリ管理デー...

大きな太陽の天気アイコンを純粋な CSS で記述する方法の例

効果効果図は以下のとおりです実装のアイデアDivは太陽の長方形の光と影を実現します前の疑似要素は、既...

ウェブページ制作でウェブフォントファイルにベクターアイコンを追加する方法

ご存知のとおり、コンピューターには 2 種類の画像があり、1 つはビットマップ、もう 1 つはベクタ...

MySQL のインデックス障害の一般的なシナリオと回避方法

序文これまでにも、一部の SQL ステートメントを不適切に使用すると MySQL インデックスが失敗...

Linux ブートシステム方式の分析

この記事では、Linux システムを起動する方法について説明します。ご参考までに、詳細は以下の通りで...

純粋な CSS ドロップダウン メニュー

成果を達成する実装コードhtml <div id="コンテナ"> &...