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に追加できない問題を解決する方法

推薦する

画像の一時停止を実現するjQueryプラグイン

この記事では、画像の一時停止を実現するためのjQueryプラグインの具体的なコードを参考までに共有し...

HTML の 5 種類のスペースの意味

HTML には、幅の異なる 5 つのスペース エンティティが用意されています。非改行スペース ( )...

win10にUbuntu18デュアルシステムをインストールするとmmx64.efiが見つからないという問題が発生する

Ubuntu 18のインストール中に、USBディスクからUbuntuのインストールを開始すると、mm...

MySQL のあまり知られていないソート方法

序文ORDER BY 字段名升序/降序、このソートステートメントは皆さんご存知だと思いますが、特殊な...

MySQL sql_mode の変更が有効にならない理由と解決策

目次序文シナリオシミュレーション要約する序文最近、sql_mode の話題については何度も話し合われ...

vue $setは配列コレクションオブジェクトへの値の割り当てを実装します

Vue $set 配列コレクションオブジェクトの割り当てVue カスタム配列オブジェクト コレクショ...

MySQL の group by に関する簡単な説明

目次1. はじめに2. ユーザーテーブルを準備する2.1 グループ化ルール2.2 グループの使用2....

vue router-view のネストされた表示実装

目次1. ルーティング構成2. Vueページのネスト3. ネストされた関係1. ルーティング構成 定...

テーブルの4辺を上下左右にスクロールするように固定する方法

質問:最近、プロジェクトの統計を行っていたときに、テーブルを上下にスクロールしたときにテーブルの先頭...

Linux で履歴コマンドを表示および実行する方法

履歴コマンドを表示し、指定されたコマンドを実行します owen@owen:~/owen/softwa...

高性能なウェブサイトのための14のテクニック

オリジナル: http://developer.yahoo.com/performance/rule...

Docker イメージのプルとタグ操作 pull | tag

Fabric プロジェクトのソースコードを読み直してみたところ、Docker の部分でよくわからな...

ウェブデザインの仕事に応募する方法

<br />みなさんこんにちは!ここで皆さんとチャットできて光栄です! (*^__^*)...

Docker インストール Nginx チュートリアル 実装図

Nginx をインストールして試してみましょう。画像はクラスであり、コンテナはオブジェクトであること...