ホームページ  >  記事  >  ウェブフロントエンド  >  ネイティブJavaScriptイベントの徹底分析_基礎知識

ネイティブJavaScriptイベントの徹底分析_基礎知識

WBOY
WBOYオリジナル
2016-05-16 16:23:411060ブラウズ

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 までご連絡ください。