javascriptイベントバインド学習のポイント

15070 ワード

イベントバインディングは2つに分かれています.一つは伝統的なイベントバインディング(インラインモデル,スクリプトモデル)であり、一つは現代的なイベントバインディング(DOM 2段モデル)です.近代的なイベントは、従来のバインディングにより、より強力で便利な機能を提供します.
一つの伝統的なイベントのバインディングの問題
従来のイベントバインディングにおけるインラインモデルは議論されず、ほとんど使われない.まずスクリプトモデルを見てみます.スクリプトモデルは関数をイベント処理関数に割り当てます.従来のバインディング:

window.onload=function(){
 var box=document.getElementById('box');
 box.onclick = function(){
  alert('Lee');
 };
};



問題1:一つのイベントハンドラが二つのイベントをトリガする.
一つのページに二つ以上のjsがあって、一つ目のjsは一番目のプログラム開発で、二つ目のjsは二つ目のプログラマが開発しました.最初のwindow.onloadはカバーされました.

window.onload=function(){
 alert('Lee');
};

window.onload=function(){
 alert('Mr.lee');
} 

結果はMr.leeだけプリントしました.
実はこの問題を解決する方法があります.次の二つの形式を見てください.a:

alert(window.onload);//       window.onload,    null

window.onload=function(){
 alert('Lee');
};

alert(window.onload);//     window.onload,      function

window.onload=function(){
 alert('Mr.lee');
} 

b:

alert(typeof window.onload);//     window.onolad,      undefined,    object,

window.onload=function(){
 alert('Lee');
};

alert(typeof window.onload);//     window.onload,         function

window.onload=function(){
 alert('Mr.lee');
}

だから解決方法ができました.

 window.onload=function(){
 alert('Lee');
};

if(typeof window.onload=='function'){
 var saved=null;//         
 saved=window.onload;
}

//saved   window.onload,saved()   window.onload(),  window.onload()     
//  saved()   window.onload=function(){}

window.onload=function(){
 if(saved){
  saved();//        window.onload=function(){}
 }
 alert('Mr.lee'); //     
}

問題二:イベントチェッチャは一つのidをboxのdivに切り替えて、中の背景redとblueを直接に切り替えて、そして切り替える前に一度ボックスを弾きます.

window.onload=function(){
 var box=document.getElementById('box');
 box.className="red";
 box.onclick=function(){
  alert('Lee'); //      
  blue.call(this);//            ,     this     window,      call  
 };
}

function blue(){
 this.className="blue";
 this.onclick=red;
 
}

function red(){
 this.className="red";
 this.onclick=blue;
}

上のコードは切替機能を実現しましたが、弾枠は一回だけ実行しました.

//      
//obj   window
//type   onload
//fn   function(){}
function addEvent(obj,type,fn){
 //         
 var saved=null;
 if(typeof obj['on'+type]=='function'){
  saved=obj['on'+type];//       
 }
 obj['on'+type]=function(){
  if(saved){
   saved();
  }
  fn.call(this);
 }
 
}
addEvent(window,'load',function(){
 var box=document.getElementById("box");
 //addEvent(box,'click',function(){ //    ,      ,     
 // alert('ss');
 //});
 addEvent(box,'click',blue);
});

function red(){
 this.className="red";
 addEvent(box,'click',blue);
}

function blue(){
 this.className="blue";
 addEvent(box,'click',red);
}

//         ,       ,    :too much recursion,     
//             
//    ,       ,      

上記のコードによって注釈中のエラーが発生しました.解決方法は以下の通りです.

//      
//obj   window
//type   onload
//fn   function(){}
function addEvent(obj,type,fn){
 //         
 var saved=null;
 if(typeof obj['on'+type]=='function'){
  saved=obj['on'+type];//       
 }
 obj['on'+type]=function(){
  if(saved){
   saved();
  }
  fn.call(this);
 }
 
}


//         ,       ,    :too much recursion,     
//             
//    ,       ,      


//      
function removeEvent(obj,type){
 if(obj['on'+type]){
  obj['on'+type]=null;
 }
}


addEvent(window,'load',function(){
 var box=document.getElementById("box");
 //addEvent(box,'click',function(){ //    ,      ,     
 // alert('ss');
 //});
 addEvent(box,'click',blue);
});

function red(){
 this.className="red";
 removeEvent(this,'click');
 addEvent(box,'click',blue);
}

function blue(){
 this.className="blue";
 removeEvent(this,'click');
 addEvent(box,'click',red);
}

二W 3 Cイベント処理関数addEventListener()とremoveEveventListener()W 3 Cイベント処理関数の二つは、addEventListener()とremoveveveveveventListener()です.
//W 3 C持参の2つの追加イベントと削除イベント1.問題をカバーし、解決する

window.addEventListener('load',function(){
 alert('Lee');
},false);

window.addEventListener('load',function(){
 alert('Mr.Lee');
},false);

window.addEventListener('load',function(){
 alert('Mrs.Lee');
},false);

2.同じ関数で遮断された問題を解決する.

window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
function init(){
 alert('Lee');
}
3.thisを伝えることができるかどうか、解決例1:

window.addEventListener('load',function(){
 var box=document.getElementById('box');
 box.addEventListener('click',function(){
  alert(this);
 },false);
},false);

例2:

window.addEventListener('load',function(){
 var box=document.getElementById('box');
 box.addEventListener('click',blue,false);
},false);

function red(){
 this.className="red";
 this.removeEventListener('click',red,false);
 this.addEventListener('click',blue,false);
}

function blue(){
 this.className="blue";
 this.removeEventListener('click',blue,false);
 this.addEventListener('click',red,false);
}

4.カバーされていないか、または一回しか実行できない追加の方法を追加して、解決します.

window.addEventListener('load',function(){
 var box=document.getElementById('box');
 box.addEventListener('click',function(){
  alert('Lee');
 },false);
 box.addEventListener('click',blue,false);
},false);
以上のように、W 3 Cはこれらの問題を完璧に解決しています.とても使いやすいです.しかし、IE 8と以前のブラウザはサポートしていません.自分のイベントを採用しています.もちろん、IE 9はW 3 Cの二つのイベント処理関数を完全にサポートしています.
W 3 Cは発泡および捕獲方式を設定することができる.
W 3 C標準対応のブラウザは、イベントを追加する際に、addEvent Listener(event,fn,useCapture)方法を用いて、基本的に3番目のパラメータであるuseCaptureはBoolean値であり、イベントがイベントキャプチャ時に実行されるか、それともイベントの発泡時に実行されるかを設定します.W 3 Cに対応していないブラウザ(IE)はatachEvent()の方法で設定されていませんが、IEのイベントモデルはデフォルトでは、イベントの泡が発生した時に実行されます.つまり、useCaptureがfalseに等しい時に実行されるので、イベントを処理する時にuseCaptureをfalseに設定するのは比較的安全です.
イベントキャプチャフェーズ:イベントは、イベントターゲットに捕獲されるまで、最上位のタブから下へ検索される.イベントの泡立ち段階:イベントはイベントのターゲットから始まり、ページの最上位のタブまで泡を上げる.イベントの伝播は阻止できます.W 3 cでは、stopPropagation()方法を使ってIEの下にcancel Bubble=trueを設定します.
三.IEイベントハンドリング関数
atachEvent()とdetachEvent()IEはDOMと同様の2つの方法を実現した:atachEvent()とdetachEvent().この2つの方法は同じパラメータを受け入れる.イベント名と関数.
この二つの関数を使う時、まず区別を言います.1.IEは捕獲をサポートしないで、発泡だけをサポートします.2.IE追加イベントは重複の関数をブロックできません.3.IEの中のthisはDOMオブジェクトではなくwindowを指す.4.伝統的なイベントでは、IEはイベントの対象を受け入れることができませんが、atch Eventを使ってもいいですが、違いがあります.
1.問題をカバーして解決しましたが、違っています.結果はMrss.Lee、Mr.Lee、最後はLeeです.

window.attachEvent('onload',function(){
 alert('Lee');
});

window.attachEvent('onload',function(){
 alert('Mr.Lee');
});
window.attachEvent('onload',function(){
 alert('Mrs.Lee');
});

2.同じ関数で遮断された問題が解決されていません.

window.attachEvent('onload',init);
window.attachEvent('onload',init);

function init(){
 alert('Lee');
}

3.thisを伝えることができるかどうか、できません.thisとはwindowのことです.コール方法が必要です.

window.attachEvent('onload',function(){
 var box=document.getElementById('box');
 box.attachEvent('onclick',function(){
  //alert(this===box);
  alert(this===window); //true
 });
});
次の方法はwindow.event.srcelementを通じてです.コードは以下の通りです

window.attachEvent('onload',function(){
 var box=document.getElementById('box');
 box.attachEvent('onclick',blue);
});

function red(){
 var that=window.event.srcElement;
 that.className="red";
 that.detachEvent('onclick',red);
 that.attachEvent('onclick',blue);
}

function blue(){
 var that=window.event.srcElement;
 that.className="blue";
 that.detachEvent('onclick',blue);
 that.attachEvent('onclick',red);
}

4.カバーされていないか、または一回だけ実行して解決する追加の方法を追加します.
従来のバインディングでは、IEはW 3 Cのようにイベントオブジェクトを転送することはできませんが、atachEvent()を使用しても良いです.

 window.attachEvent('onload',function(){
 var box=document.getElementById('box');
 box.onclick=function(evt){ //    IE        evt
  alert(evt);//undefined
 }
 box.attachEvent('onclick',function(evt){
  alert(evt);//object
  alert(evt.type);//click
  alert(evt.srcElement.tagName);//DIV
  alert(window.event.srcElement.tagName);//DIV
 });
});
ブラウザ間の互換性
ブラウザをまたいでイベントを追加します.

function addEvent(obj,type,fn){
 if(obj.addEventListener){
  obj.addEventListener(type,fn,false);
 }else if(obj.attachEvent){
  obj.attachEvent('on'+type,fn);
 }
}
ブラウザをまたいでイベントを削除

function removeEvent(obj,type,fn){
 if(obj.removeEventListener){
  obj.removeEventListener(type,fn,false);
 }else if(obj.detachEvent){
  obj.detachEvent('on'+type,fn);
 }
}
ブラウザをまたいでターゲットを取得します.

function getTarget(evt){
 if(evt.target){
  return evt.target;
 }else if(window.event.srcElement){
  return window.event.srcElement;
 }
}
呼び出し方法:

addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'click',blue);
});


function red(evt){
 var that=getTarget(evt);
 that.className="red";
 removeEvent(that,'click',red);
 addEvent(that,'click',blue);
}

function blue(evt){
 var that=getTarget(evt);
 that.className="blue";
 removeEvent(that,'click',blue);
 addEvent(that,'click',red);
}

四.事件の対象のその他の追加
relatedTargetイベント
w 3 cのうちの一つのrelatedTargetイベント.たとえば:

addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'mouseover',function(evt){
  alert(evt.relatedTarget); //    box     DOM  
 });
 
 addEvent(box,'mouseout',function(evt){
  alert(evt.relatedTarget); // box       DOM  
 });
});
IEは、移動のための2つのグループのプロパティfrom ElementとtoElementを提供し、それぞれmouseoverとmouseoutに対応する.

addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'mouseover',function(){
  alert(window.event.fromElement.tagName); //    box     DOM  
 });
 
 addEvent(box,'mouseout',function(){
  alert(window.event.toElement.tagName); // box       DOM  
 });
});
PS:froomElementとtoElementが反対のマウスイベントにそれぞれ対応すると意味がありません.
残りはブラウザをまたいでの対応です.

function getTarget(evt){
 var e=evt || window.event;
 if(e.srcElment){ //IE
  if(e.type=='mouseover'){
   return e.fromElement.tagName;
  }else if(e.type="mouseout"){
   return e.toElement.tagName;
  }
 }else if(e.relatedTarget){ //w3c
  return e.relatedTarget;
 }
}
ジャンプ操作をブロック
イベントのデフォルトをキャンセルすることは、falseに戻ることです.

link.onclick=function(){
 alert('Lee');
 return false;
}
PS:return falseですが、この機能は実現できますが、手抜かりがあります.最後まで書かなければなりません.このようにして当選のコードが実行されたら、リターンfalseが実行されない可能性があります.第二:return falseは、一番前に書いた後のカスタム操作が無効になります.したがって、最善の方法は、最初にデフォルトの行動を阻止することであり、後のコードを実行することもできる.

link.onclick=function(evt){
 evt.preventDefault;//w3c,      
 alert('Lee');
}

link.onclick=function(evt){
 window.event.returnValue=false;//IE,      
 alert('Lee');
}

ブラウザ間の互換性:

function preDef(evt){
 var e=evt || window.event;
 if(e.preventDefault){
  e.preventDefault();
 }else{
  e.returnValue=false;
 }
}
右クリックメニューcontextmenu互換:

function preDef(evt){
 var e=evt || window.event;
 if(e.preventDefault){
  e.preventDefault();
 }else{
  e.returnValue=false;
 }
}

addEvent(window,"load",function(){
 var body=document.getElementsByTagName('body')[0];
 addEvent(body,'contextmenu',function(evt){
  preDef(evt);
 })
});

PS:contextmenuイベントはよく使われています.これは直接ブラウザの互換性が安定しています.
アンインストール前のイベント:beforeunloadこのイベントは、このページを離れる時に対応するヒントを与えることができます.

addEvent(window,'beforeonload',function(){
 preDef(evt);
});
マウスホイールとDOMMouseScurollは、マウスの上下ホイールの距離を取得します.

addEvent(document,'mousewheel',function(evt){ //   
 alert(getWD(evt));
});

addEvent(document,'DOMMouseScroll',function(evt){ //  
 alert(getWD(evt));
});

function getWD(evt){
 var e=evt|| window.event;
 if(e.wheelDelta){
  return e.wheelDelta;
 }else if(e.detail){ //  
  return -evt.detail*30;
 }
}

PS:ブラウザの検出により、フォックスはDOMMouseScrrollのみを実行すると判定できます.
DOMContentLoadedイベントとreadystatechangeイベント
DOMContentLoadedイベントとreadystatechangeイベント、DOMロードに関するイベント.