検索
ホームページウェブフロントエンドjsチュートリアルネイティブJavaScriptイベントの徹底分析_基礎知識

Write Less Do More フレームワークである JQuery は、使いすぎると必然的にネイティブ JS についての知識が過剰になります。

Xiao Cai は実際にはこのブログを書きたくなかったのですが、非常に基本的なことのように思えましたが、ネイティブ JS イベントのバインドとバインド解除がインターネット上では説明できないことを見て、一般的な科学を行うことにしました。

まず最初に断っておきますが、私は Xiaocai についてあまり知りません。ただ私の考えを皆さんと共有したいだけです。

DOM0 イベントモデル

イベント モデルは常に進化しており、初期のイベント モデルは DOM0 レベルと呼ばれます。

DOM0 イベント モデル。すべてのブラウザでサポートされています。

イベント名を dom オブジェクトに直接登録します。これは、DOM0 での記述方法と同じです。次に例を示します。

コードをコピーします コードは次のとおりです:

document.getElementById("test").onclick = function(e){};

onclickイベントを登録することを意味します。もちろん、この書き方と同じ意味です:

コードをコピーします コードは次のとおりです:

document.getElementById("test")["onmousemove"] = function(e){};

これは何もありません。これらは、JS オブジェクト属性にアクセスする 2 つの方法にすぎません。[] フォームは主に、属性名が正当な識別子ではないという問題を解決するためのものです。たとえば、object.123 は間違いなくエラーを報告します。ただし、object["123"] はこの問題を回避します。同時に、[] の記述メソッドにより、属性名を表すために文字列が使用され、実行時にイベントを動的にバインドできます。

さらに詳しく言えば、イベントがトリガーされると、イベント オブジェクトを表すパラメーター e がデフォルトで渡され、e を通じて、クリックの座標、特定のオブジェクトなど、多くの有用な情報を取得できます。イベントをトリガーしたDOM要素など。

同じ DOM ノードに登録できる DOM0 に基づくイベントは 1 つだけです。後で登録された同じイベントは、以前に登録されたイベントを上書きします。例:

コードをコピーします コードは次のとおりです:

var btn = document.getElementById("テスト");
btn.onmousemove = function(e){
alert("ok");
};
btn["onmousemove"] = function(e){
アラート("ok1");
};

結果は ok1 になります。

次にこれについて話しましょう。イベントがトリガーされると、これはイベントがトリガーされた DOM オブジェクトを参照します。例:

コードをコピーします コードは次のとおりです:

var btn = document.getElementById("テスト");
btn.onmousemove = function(e){
アラート(this.id);
};

結果は出力テストです。イベントはtestというIDでDOMノードに登録されているので、イベントがトリガーされると当然DOMノードを表し、DOMノードからイベントが呼び出されることが分かります。

したがって、イベントを再度登録して値を null に設定するだけで、イベントをキャンセルするのは非常に簡単です。たとえば、

コードをコピーします コードは次のとおりです:

var btn = document.getElementById("テスト");
btn.onclick = function(e){
alert("ok");
};
btn.onclick = null;

原則として、最後に登録されたイベントは以前のイベントを上書きする必要があり、最後に登録されたイベントは null に設定され、イベントのバインドが解除されます。

事態はまだ終わっていません。DOM0 イベント モデルには、HTML で直接記述されたイベントも含まれています。例:

コードをコピーします コードは次のとおりです:


この方法で登録されたイベントもカバレッジ原則に従い、1 つだけ登録でき、最後のものが有効になります。

違いは、この方法で登録されたイベントは関数を動的に呼び出すことと同等 (eval に少し似ています) であるため、イベント オブジェクトは渡されません。同時に、これはウィンドウではなくウィンドウを指します。イベントをトリガーした DOM オブジェクト。

DOM2 イベントモデル

DOM0 と比較して、DOM2 イベント モデルは次の 2 点のみを理解します。

DOM2 は、同じタイプの複数のイベントを登録するための同じ DOM 要素をサポートしています。

· DOM2 では、キャプチャとバブリングの概念が追加されています。

DOM2 イベントは addEventListener と RemoveEventListener を通じて管理されます。これが標準です。

ただし、IE8 以下のブラウザでは、面白がって対応するattachEvent と detachEvent が作成されています。知識が不足しているため、この記事では説明しません。

AddEventListener はもちろん登録されたイベントであり、「イベント名」、「イベント コールバック」、「キャプチャ/バブル」という 3 つのパラメータがあります。例:

コードをコピーします コードは次のとおりです:

var btn = document.getElementById("テスト");
btn.addEventListener("クリック", function(e){
alert("ok");
}, false);

イベント名については言うまでもありませんが、DOM0 と比較すると、先頭の on が取り除かれているだけです。

イベントのコールバックも理解しやすいです。イベントがトリガーされたときに通知する必要があります。コールバック中に、DOM0 と同様に、デフォルトでイベント パラメータが渡されます。これは、イベントをトリガーした dom ノードを指します。

最後のパラメータはブール型で、true はキャプチャ イベントを表し、false はバブリング イベントを表します。実際、これは簡単に理解できる図です:

要素がイベントをトリガーすると、最初に通知されるのはウィンドウ、次にドキュメントというように、実際にイベントをトリガーする要素 (ターゲット要素) が見つかるまで、このプロセスがキャプチャされることを意味します。次に、イベントはターゲット要素からバブリングを開始し、ウィンドウ オブジェクトに到達するまで順番に出力されます。このプロセスはバブリングです。

なぜこのようなデザインになっているのでしょうか?これには深い歴史的由来があるようで、Xiaocai はそれについて詳しくないので、くだらない話はしません。

バブリング イベントの前にキャプチャ イベントがトリガーされていることがわかります。

次のような HTML 構造があるとします。

コードをコピーします コードは次のとおりです:




次に、外側の div に 2 つのクリック イベント、つまりキャプチャ イベントとバブリング イベントを登録します。コードは次のとおりです。

コードをコピーします コードは次のとおりです:
var btn = document.getElementById("テスト");
//イベントをキャプチャ
btn.addEventListener("クリック", function(e){
アラート("ok1");
}, true);
//バブルイベント
btn.addEventListener("クリック", function(e){
alert("ok");
}, false);

最後に、内側の div をクリックすると、最初に ok1 がポップアップし、次に ok がポップアップします。上の模式図と組み合わせると、外側の div が図の本体に相当し、内側の div が図の下部の div に相当します。これは、最初にキャプチャ イベントが実行され、次にバブリング イベントが実行されることを示しています。 。

なぜ内側の div をクリックすることを強調する必要があるのでしょうか?実際にイベントをトリガーする DOM 要素は内部にある必要があるため、概略図からわかるように、外部の DOM 要素にはキャプチャ イベントとバブリング イベントをシミュレートする機会があります。

キャプチャ イベントとバブリング イベントが、実際にイベントをトリガーする DOM 要素に登録されている場合はどうなるでしょうか?

HTML 構造は上記と同じで、js コードは次のとおりです。

コードをコピー コードは次のとおりです:

var btnInner = document.getElementById("testInner");
//バブルイベント
btnInner.addEventListener("クリック", function(e){
alert("ok");
}, false);
//イベントをキャプチャ
btnInner.addEventListener("クリック", function(e){
アラート("ok1");
}, true);

もちろん、内側の div をクリックすると、最初に ok が表示され、次に ok1 が表示されます。理論的には、キャプチャ イベントが最初にトリガーされる必要があります。つまり、ok1 が最初にポップアップする必要がありますが、実際にイベントをトリガーする dom 要素にイベントを登録するため、これは特別です。これは、図内の div に登録するのと同等です。図からわかるように、イベントをトリガーする実際の DOM 要素は、キャプチャされたイベントの終了点とバブリング イベントの開始点であるため、ここではイベントの区別はなく、どちらが先に登録されることになります。最初に実行されました。この例では、バブリングイベントが最初に登録されているため、最初に実行されます。

この原則は、同じ種類の複数のイベントに適用されます。たとえば、3 つのバブリング イベントが一度に登録された場合、実行順序は登録順に基づいて、最初に登録され、最初に実行されます。例:

コードをコピーします コードは次のとおりです:

var btnInner = document.getElementById("testInner");
btnInner.addEventListener("クリック", function(e){
alert("ok");
}, false);
btnInner.addEventListener("クリック", function(e){
アラート("ok1");
}, false);
btnInner.addEventListener("クリック", function(e){
アラート("ok2");
}, false);

もちろん、結果は ok、ok1、ok2 が順に表示されます。

イベント モデルをさらに理解するために、外側の div と内側の div が同時にイベントをキャプチャする場合、内側の div がクリックされたときに外側の div のイベントがトリガーされる必要があるという別のシナリオがあります。まずコードは次のとおりです:

コードをコピーします コードは次のとおりです:

var btn = document.getElementById("テスト");
var btnInner = document.getElementById("testInner");
btnInner.addEventListener("クリック", function(e){
alert("ok");
}, true);
btn.addEventListener("クリック", function(e){
アラート("ok1");
}, true);

結果として、ok1 が最初に表示されます。

外側の div と内側の div の両方がバブリング イベントとして登録されている場合、内側の div をクリックすると、内側の div イベントが最初に実行される必要があります。原理は同じです。

注意深い読者は、div がネストされている場合、内側の div をクリックすると外側の div もイベントをトリガーすることに気づくでしょう。これは問題があるようです。

クリックされたのは明らかに内側の div ですが、外側の div のイベントもトリガーされます。これは確かに問題です。

実際、イベントがトリガーされると、デフォルトでイベント オブジェクトが渡されます。このイベント オブジェクトには stopPropagation メソッドがあり、このメソッドを通じてバブリングを防ぐことができます。 div はイベントを受信しません。コードは次のとおりです:

コードをコピーします コードは次のとおりです:

var btn = document.getElementById("テスト");
var btnInner = document.getElementById("testInner");
btn.addEventListener("クリック", function(e){
アラート("ok1");
}, false);
btnInner.addEventListener("クリック", function(e){
// 泡立ちを止める
e.stopPropagation();
alert("ok");
}, false);

最後に、事件の解決方法について話しましょう。イベントの削除構文: btn.removeEventListener("Event Name", "Event Callback", "Capture/Bubble");

これはバインディング イベントのパラメータと同じです。詳しく説明してください:

· イベントの名前は、どのイベントが解決されるかを示します。

・ イベント コールバックは関数であり、この関数はイベントを登録する関数と同じである必要があります。

· イベントのタイプ、ブール値、これはイベントを登録するときのタイプと一致している必要があります。

言い換えれば、名前、コールバック、タイプはすべて連携してどのイベントを解放するかを決定し、すべてが不可欠です。例:

コードをコピーします コードは次のとおりです:

var btn = document.getElementById("テスト");
//コールバックを変数に保存します
var fn = function(e){
alert("ok");
};
//バインド
btn.addEventListener("クリック", fn, false);
//リリース
btn.removeEventListener("クリック", fn, false);

登録したイベントを解放したい場合は、コールバック関数を保存しなければ解放できません。

DOM0 と DOM2 の混合

物事はすでに非常に混乱していますが、これは混合使用であり、人々は生きられなくなります。 。 。

心配しないでください。DOM0 モデルと DOM2 モデルはそれぞれ独自のルールに従い、相互に影響しません。

一般的に言えば、どちらが先に登録するか、どちらが先に実行するかが重要であり、残りは重要ではありません。

追記

現時点では、ネイティブ JS イベントについてはほぼ説明済みです。読者はこれについてのみ知っています。他の知識ポイントを追加することは歓迎です。

実際のアプリケーションでは、本物の専門家は、これほど多くのイベントを愚かに登録することはありません。通常の状況では、最も外側の dom 要素にイベントを登録するだけで済み、その後、DOM のキャプチャおよびバブリング メカニズムを通じて実際のトリガーを見つけることができます。イベントの要素を呼び出し、最後に、イベントをトリガーした DOM 要素によって提供される情報に基づいてコールバックが呼び出されます。

つまり、イベントをブラウザに依存するのではなく、専門家が自分で管理することで効率が向上し、互換性が確保されるのが JQuery ですよね~

さて、チュートリアルはこれで終わりです。読者のお役に立てば幸いです。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

CSS原生嵌套语法来了!使用指南速览!CSS原生嵌套语法来了!使用指南速览!Feb 08, 2023 pm 03:31 PM

目前,CSS 原生嵌套语法处于开发者试用状态,CSS 工作组正在制定相关规范,Chrome 浏览器预计将于 112 版本正式推出 CSS 原生嵌套功能。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール