イベントの操作は、addEvent、fireEvent、removeEvent の 3 つのイベント メソッドにほかなりません。一般に、lib は、互換性メモリ リークなどの問題を解決するために、ブラウザによって提供される関数にいくつかの拡張を加えます。 3 番目の質問は、domReady のステータスを取得する方法です。
6.1 イベントパッケージ
ブラウザイベントの互換性は頭痛の種です。 IE のイベントはグローバル ウィンドウの下にありますが、Mozilla のイベントはイベント ソース パラメーターがコールバック関数に渡されることです。他にも多くのイベント処理メソッドがあります。
Jquery はイベント パッケージを提供します。これは他のライブラリが提供するものよりも少し単純ですが、使用するには十分です。
// イベントをラップします。
修正: function(event) {
if (event[expando] == true) return event;// イベントがラップされたことを示します
// 元のイベントを保存し、そのイベントを複製します。
varoriginalEvent = イベント; ①
イベント = {originalEvent : originalEvent};
for (var i = this.props.length, prop;i;) {
-i]; event[prop] =originalEvent[prop]; }
event[expando] = true;event.preventDefault = function() { ②
// 元のイベント
if (originalEvent. PreventDefault)
originalEvent.preventDefault();
originalEvent.returnValue = false;
Event.stopPropagation = function() {
};正しい timeStamp
event.timeStamp =event.timeStamp || now();
// 正しいターゲット
if (!event.target) ③
target =event.srcElement ||
if (event.target.nodeType == 3)//テキストノードが親ノードです。
Event.target =event.target.parentNode;
// relationshipTarget
if (!event.popularTarget &&event.fromElement)event.popularTarget =event.fromElement ==event.target
? .toElement :event.fromElement;
// 欠落している場合は pageX/Y を計算し、clientX/Y が利用可能
if (event.pageX == null &&event.clientX != null) { ⑥
var doc = document.documentElement, body = document.body;
event.pageX =event.clientX
(doc && doc.scrollLeft || body && body.scrollLeft || 0)
- (doc .clientLeft || 0) 0);
event.pageY =event.clientY
(doc && doc.scrollTop || body && body.scrollTop || 0)
- (doc.clientTop || 0);
// キーイベントのどれを追加します
if (!event.that && ((event.charCode ||event.charCode === 0) ⑦
?event.charCode :event.keyCode ))
event.that =event.charCode ||event.keyCode;
// Mac 以外のブラウザにメタキーを追加します
if (!event.metaKey &&event.ctrlKey ) ⑧
event.metaKey =event.ctrlKey;
// クリック用に次を追加します: 1 == left; 3 == right
// 注: ボタンは正規化されていないため、使用しないでください。 it
if (!event.that &&event.button) ⑨
event.that = (event.button & 1 ? 1 : (event.button & 2
? 3 : (event.button & 4) ? 2 : 0)));
}、
上記のコードは、①で元のイベントの参照を保持し、元のイベントを複製します。このクローン イベントをラップします。 ② 元のイベントに対して、preventDefault メソッドと stopPropagation メソッドを実行して、デフォルトのイベント アクションの発生を防止するかどうか、およびバブリング イベントの上方への送信を停止するかどうかを決定します。
③IEでsrcElementを使用する場合、同時にテキストノードイベントの場合、ターゲットを親ノードに渡すように修正しました。
④relationTarget はマウスアウトとマウスオーバーにのみ役立ちます。 IE では to と from の 2 つの Target 変数に分割されますが、Mozilla では分割されません。互換性を確保するために、relationalTarget を使用して統合します。
⑥はイベントの座標位置です。これはページに相対的なものです。ページをスクロールできる場合は、クライアントにスクロールを追加する必要があります。 IE では、デフォルトの 2px の本文境界線も減算する必要があります。
⑦のポイントは、キーボードイベントのキーをevent.thatの属性に統一することです。 Ext での実装は ev.charCode || ev.keyCode 0; で、event.that にマウス イベント キーを統合します。 charCode と ev.keyCode の一方は文字キーであり、もう一方は文字キーではありません。 ⑨ & メソッドを使用して互換性を処理します。 Ext は、次の 3 行で互換性の問題を解決します。
var btnMap = Ext.isIE ? {1:0,4:1,2:2} : (Ext.isSafari ? {1:0,2:1,3:2} : {0:0 ,1:1,2:2}); this.button = e.button ? btnMap[e.button] : (e.this ? e.that-1 : -1); ①②③④⑤⑥⑦⑧⑨⑩ >
6.2 イベント処理
Jquery は、イベントを登録、削除、起動するためのメソッドをいくつか提供します。
6.2.1 登録
イベントを登録するために、jquery はバインド、ワン、トグル、ホバーの 4 つのイベント登録メソッドを提供します。バインドは最も基本的なメソッドです。 1 つは 1 回だけ実行するように登録されているメソッドで、toggle は交互に実行するように登録されているメソッドです。ホバーはマウスホバリングを登録する方法です。
Return type == "unload" ? this.one(type, data, fn) : this
.each(function() {// fn || data, fn && data は data パラメータを認識しますはオプションです
jQuery.event.add(this, type, fn || data, fn && data)
}); unload イベントは 1 回のみ実行でき、他のイベントはデフォルトの登録方法を使用します。
// ワンタイム イベント ハンドラー関数を、一致する各要素の特定のイベント (クリックなど) にバインドします。
//各オブジェクト上で、このイベント ハンドラーは 1 回だけ実行されます。その他のルールはbind()関数と同じです。
// このイベント ハンドラーは、デフォルトの動作 (ブラウザー) を防ぐために使用できるイベント オブジェクトを受け取ります。
// デフォルトの動作をキャンセルしてイベントのバブリングを防止したい場合、このイベント処理関数は false を返す必要があります。
コードをコピー
コードは次のとおりです:
jQuery.event.add(this, type, one, fn &&データ);
});
One と binding は基本的に同じです。違いは、jQuery.event.add を呼び出すときに、登録されているイベント処理関数が少し調整されることです。 1 つは、受信イベント処理関数をプロキシするために jQuery.event.proxy と呼ばれるものです。イベントによってこのエージェントの関数の呼び出しがトリガーされると、まずイベントがキャッシュから削除され、次に登録されたイベント関数が実行されます。 fn で登録したイベント関数の参照を取得するクロージャの適用例です。
//ホバー イベント (マウスがオブジェクト上を移動し、オブジェクトから移動する) をシミュレートするメソッド。
//これは、頻繁に使用されるタスクに「保持」状態を提供するカスタム メソッドです。
//マウスが一致する要素上に移動すると、指定された最初の関数がトリガーされます。マウスがこの要素の外に出ると、
/ は指定された 2 番目の関数をトリガーします。さらに、マウスがまだ特定の要素 (div 内の画像など) にあるかどうかの検出も伴います。
// もしそうであれば、トリガーせずに「ホバー」状態を維持し続けます。 move-out イベント (mouseout イベントを使用した一般的なエラーを修正)。
ホバー: function(fnOver, fnOut) {
return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
},
ホバーはバインドに基づいています。
//クリックするたびに関数を順番に呼び出します。
toggle: function(fn) {
var args = argument, i = 1;
while (i jQuery.event.proxy ( fn, args[i ]);//変更されたものは args
return this.click(jQuery.event.proxy(fn, function(event) {//Assign GUID this.lastToggle = (this. lastToggle || 0) % i; // 前の関数 events.preventDefault(); // デフォルトのアクションを防止します
// パラメータで関数を実行し、配列のようなパラメータを使用できます
return args[this. lastToggle].apply(this,arguments)||false;
}));
},
Toggle のパラメータは複数指定できます。まず、それらをコーディングして UUID を生成します。次に、 click メソッドを呼び出して、エージェントのコールバックを再度登録します。この関数は、イベントがトリガーされると実行され、最初にパラメーター内の関数が最後に実行された時刻が計算されます。次に、デフォルトのアクションを防止します。次に、実行する次の関数を見つけます。
//一般的に使用されるイベント メソッドを jquery オブジェクトに追加します
jQuery.each(
("blur, focus,load,size,scroll,unload,click,dblclick,"
"mousedown ,mouseup,mousemove,mouseover,mouseout,change,select,"
"submit,keydown,keypress,keyup,error").split(","),
function(i, name) {jQuery.fn [name] = function(fn) {
return fn? this.bind(name, fn) : this.trigger(name);
イベント処理メソッドには、上記のクリックが含まれます。ここでは、登録するためにbindがまだ呼び出されていることがわかります。もちろん、プログラムを通じてイベントをトリガーすることもできます。
上記のメソッドの多くはイベントを登録するもので、最終的には jQuery.event.add(); に分類され、登録関数が完了します。 Dom0 または DOM1 のイベント メソッドを使用する場合は、elem.onclick=function(){} を使用して、要素の特定のイベントに対するハンドラー関数を登録します。この最大の欠点は、各イベントが単なる処理関数であることです。 dom1 メソッドが改良され、elem.addEventListener(type, handle, false) を使用して要素イベントの複数のハンドラー関数を登録できるようになりました。
この処理方法は完璧ではありません。このイベントを一度だけ実行するのは少し面倒です。イベントのリスニングをキャンセルするには、イベント処理関数の最後に elem.removeEventListener を実行する必要があります。ビジネス上の問題が発生する可能性があります。イベントのリスニングをキャンセルする前に、最初のイベント処理関数が再度トリガーされた場合はどうなるでしょうか?
ブラウザによる方法もありますが、これはカスタムイベントの登録と処理をサポートしておらず、複数のイベントに同じハンドラー関数を登録することができません。
コードをコピー コードは次のとおりです: jQuery.event = {//要素にイベントを追加します。
add : function(elem, Types, handler, data) {
if (elem.nodeType == 3 || elem.nodeType == 8) return; // 空のノードまたはコメント
// IE window に渡すことはできないので、最初にコピーしてください。
if (jQuery.browser.msie && elem.setInterval) elem = window;
// ハンドラーにグローバルに一意の ID を割り当てます
if (!handler.guid) handler.guid = this.guid;
// handler.data にデータを添付します
if (data != unknown) { ①
var fn = handler
handler =this.proxy(fn,function(){return fn .apply; (this,arguments);});
handler.data = data;
}
// 要素のイベントを初期化します。 events の値が取得できない場合は、データを初期化します: {} ②
var events =jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),
// handle の値が取得できない場合は data を初期化する: function() {....} ③
handle = jQuery.data(elem, "handle")|| jQuery.data(elem, "handle") ,
function() {//トリガーの 2 番目のイベントを処理し、ページがアンロードされた後にイベントを呼び出します。
if (typeof jQuery != "unknown"&& !jQuery.event.triggered)
Return jQuery.event.handle.apply(//callee.elem=handle.elem
argument.callee.elem, argument);
}); // elem をハンドル属性として追加、メモリを防止しますローカル イベントがないため、IE でリークが発生します。
handle.elem = elem;
// 複数のイベント名を区切るにはスペースを使用します (例: jQuery(...).bind("mouseover Mouseout", fn);
jQuery.each(types. split(/s /), function(index, type) { ④
// 名前空間イベントは通常は使用されません。
var Parts = type.split(".");type = Parts[. handler.type = Parts[1];
// この要素の type イベントにバインドされたすべてのハンドラー
var handlers = events[type]; ⑤
if (!handlers) {// イベントを初期化します。ハンドラーリストが見つからない場合はキュー
handlers = events[type] = {}
// type が準備できていないか、ready のセットアップ実行が false を返す場合 ⑥
if (!jQuery.event; .special[type]|| jQuery.event.special[type].setup
.call(elem, data) === false) {// システムイベント関数を呼び出してイベントを登録します
if(elem) .addEventListener )elem.addEventListener(type,handle,false);
else if (elem.attachEvent)elem.attachEvent("on" type, handle);
}
}
//ハンドラー ID とハンドラーのフォーム属性のペアの形式はハンドラー リストに保存されます。
// events[type][handler.guid]
handlers[handler.guid] = handler; 7
/ / このイベントの使用法識別子をグローバルにキャッシュします
jQuery.event.global[type] = true;
});
elem = null; // IE のメモリ リークを防ぎます。
}、
guid: 1、
グローバル: {}、
jQuery.event.add は、jQuery.data を使用して、イベント名とイベントに関連する処理関数を有機的かつ規則的に結合し、jQuery.cache の要素に対応する空間に格納します。例を使用して追加プロセスを分析してみましょう: 次の jQuery(e1).bind("mouseover Mouseout", fn0);jQuery(e1).bind("mouseover Mouseout", fn1) ステートメントを受け取ったとします。
jQuery(e1).bind("mouseover Mouseout", fn0); の場合、②③はキャッシュから番号を取得できないので、先に初期化します。この時点のキャッシュ: {e1_uuid:{events:{},handle:fn}}。すると⑤でmouseover Mouseout名が初期化されます。この時点のキャッシュ: {e1_uuid:{events:{ Mouseover:{}, Mouseout:{}},handle:fn}}。 ⑥でブラウザイベントにハンドラー関数を登録します。次に、⑦でイベント名にハンドラー関数を追加します。この時点のキャッシュ: {e1_uuid:{events:{mouseover:{fn0_uuid:fn0},mouseout:{ fn0_uuid:fn0}},handle:fn}}。ここでは、プロキシを使用して関数の UUID を生成する役割を確認できます。
jQuery(e1).bind("mouseover Mouseout", fn1) の場合、②③は両方ともキャッシュからデータを取得します {e1_uuid:{events:{mouseover:{fn0_uuid:fn0},mouseout:{ fn0_uuid: fn0} } を実行し、⑤でmouseover:{fn0_uuid:fn0}、mouseout:{ fn0_uuid:fn0}の参照を取得します。次に、⑦でイベント名にハンドラー関数を登録します。この時点のキャッシュ: {e1_uuid:{events:{mouseover:{fn0_uuid:fn0, fn1_uuid:fn1,},mouseout:{ fn0_uuid:fn0, fn1_uuid:fn1}},handle:fn}}。
jQuery.event.add の非常に重要なタスクは、登録されたイベント関数を順序立てて保存することです。これにより、remove イベントと fire イベントの関数が見つかります。
//{elem_uuid_1:{events:{mouseover:{fn_uuid:fn1,fn_uuid1:fn2},
//mouseout:{fn_uuid:fn1,fn_uuid1:fn2}},handle:fn}}
6.2.2 トリガー
onclick などの登録されたイベント。ユーザーがこの要素をクリックすると、このイベントの登録済みイベント ハンドラーが自動的にトリガーされます。ただし、プログラムを使用してイベントのトリガーをシミュレートしたい場合は、イベントの強制トリガーを使用しなければならない場合があります。 IE では、.fireEvent() を使用してこれを実現できます。例: