js的事件的三個階段,事件委托的原理


DOM2級事件規定的事件流的三個階段:捕獲,目標,冒泡(IE8以及更早版本不支持DOM事件流);

事件流:
IE:IE事件流是事件冒泡流   Netscape事件流是事件捕獲流
IE 事件流 叫做事件冒泡,即事件開始時由最具體的元素(文檔中嵌套最深的那個節點)接收,然后逐級向上(一直到文檔)。事件捕獲與事件冒泡事件流正好相反的順序,事件捕獲的事件流是最外層逐級向內傳播。

 
        
使用 DOM0級方法指定的事件處理程序被認為是元素的方法,處理程序是在元素的作用域進行的,程序中this是引用的是當前元素
 
          
btn
var btn = document.getElementById_x_x_x("btn"); btn.onclick = function(){ alert(this.id); // 彈出btn }

  單擊元素btn后,通過this.id取得元素的屬性id,還可以通過this訪問元素的任何屬性和方法,以這種方式添加的事情處理程序在事件流的冒泡階段處理。

  也可以刪除通過DOM0級方法指定的事件處理程序,只要將事件處理程序的屬性值設置為null即可。

  btn.onclick = null; // 刪除事件處理程序;

 DOM2級事件處理程序

事件是在冒泡階段被觸發,與DOM0級方法一樣,這里添加的事件處理程序也是在其依副的元素作用域中運行,使用DOM2級添加事件處理程序的好處是可以添加多個事件處理程序,如下代碼:

var btn = document.getElementById_x_x_x("btn"); btn.addEventListener('click',function(e){ alert(this.id); },false); btn.addEventListener('click',function(e){ alert("我是來測試的"); },false);

  上面的代碼被彈出2次對話框,而在DOM0級是不可以的;它永遠是執行最后一次的。

參考:http://www.admin10000.com/document/6293.html

 

 IE事件處理的程序

btn.attachEvent('onclick',handler); function handler(e){ alert(this); // window }

  注意:attachEvent的事件名稱是onclick,而addEventListener的事件名稱是click,且IE中使用的attachEvent()與使用DOM0級方法的的主要區別在於事件處理程序的作用域,在使用dom0級情況下,事件處理程序在其所屬元素的作用域內運行,在使用attachEvent()方法的情況下,事件處理程序在全局作用域下運行,其中的this等於window。

理解標准瀏覽器下的事件對象與IE下的事件對象

 

  標准瀏覽器下的事件對象是event,比如btn點擊后;如下代碼:

var btn = document.getElementById_x_x_x("btn"); btn.onclick = function(){ console.log(event); //標准瀏覽器下打印事件對象 console.log(event.type);//'click' } btn.onclick = function(){ // IE下打印的事件對象window.event console.log(window.event); console.log(window.event.type); // 'click' }

  上面的寫法是在DOM0級上注冊事件,如果我們在Dom2級上注冊事件的話,那么就會有一個事件對象event作為參數傳入事件到函數中,如下:

var btn = document.getElementById_x_x_x("btn"); EventUtil.addHandler(btn,'click',function(e){ console.log(e); });

 理解特定事件的默認行為事件

在標准瀏覽器下
alink.onclick = function(e){ console.log(e) e.preventDefault(); }

   IE下

alink.onclick = function(){ console.log(window.event) window.event.returnValue = false; }

標准瀏覽器下與IE下的事件目標的區別

 console.log(event.target); // 打印事件目標元素 

 console.log(window.event.srcElement); 

理解標准瀏覽器與IE下阻止事件傳播的區別

 

  在標准瀏覽器下我們可以使用stopPropagation()方法來停止事件在DOM層次中的傳播,即取消事件中的冒泡或者捕獲。從而避免觸發注冊在document.body上面的事件處理程序

標准瀏覽器e.stopPropagation()

IE:window.event.cancelBubble = true

 

跨瀏覽器的事件對象

 
 
         
var EventUtil = {
   addHandler : function(element, type, handler) {
              if (element.addEventListener) {
                      element.addEventListener(type, handler, false);
              } else if (element.attachEvent) {
                    element.attachEvent("on" + type, handler);
           } else {
                     element["on" + type] = handler;
              }
    },
   removeHandler : function(element, type, handler) {
           if (element.removeEventListener) {
                   element.removeEventListener(type, handler, false);
           } else if (element.detachEvent) {
                    element.detachEvent("on" + type, handler);
           } else {
                     element["on" + type] = null;
         }
    },
   getEvent : function(event) {
         return event ? event : window.event;
 },
   getTarget : function(event) {
                return event.target || event.srcElement;
     },
   preventDefault : function(event) {
           if (event.preventDefault) {
                  event.preventDefault();
              } else {
                     event.returnValue = false;
           }
    },
   stopPropagation : function(event) {
          if (event.stopPropagation) {
                 event.stopPropagation();
             } else {
                     event.cancelBubble = true;
           }
    }
};

理解客戶區坐標位置

 

  含義是:鼠標指針在可視區中的水平clientX和垂直clientY坐標;

  如下圖所示:

  

理解頁面坐標位置pageX和pageY:

 

  pageX與pageY是指頁面坐標的位置,與clientX和clientY的區別是:它包含頁面滾動條的位置,如下圖所示:

  

但是IE8及更早的版本不支持pageX與pageY

EventUtil.addHandler(btn,'click',function(e){ e = EventUtil.getEvent(e); var pageX = e.pageX, pageY = e.pageY; if(!pageX) { pageX = e.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft); } if(!pageY) { pageY = e.clientY + (document.body.scrollTop || document.documentElement.scrollTop); } console.log("頁面X軸坐標為:"+pageX + " "+ "頁面Y軸坐標為:"+pageY); });

 理解屏幕坐標的位置

  屏幕橫坐標screenX和垂直坐標screenY屬性是相對於整個屏幕的。如下圖所示:

Javascript事件委托的原理

原理:使用事件委托技術能讓你避免對特定的每個節點添加事件監聽器;相反,事件監聽器是被添加到它們的父元素上,利用冒泡的原理,把事件加到父級上,觸發執行效果。

eg:

 

<</span>ul id="parent-list">
  <</span>li id="post-1">Item 1</</span>li>
  <</span>li id="post-2">Item 2</</span>li>
  <</span>li id="post-3">Item 3</</span>li>
  <</span>li id="post-4">Item 4</</span>li>
  <</span>li id="post-5">Item 5</</span>li>
  <</span>li id="post-6">Item 6</</span>li>
</</span>ul>
function getEventTarget(e) {
  e = e || window.event;
  return e.target || e.srcElement;
}
 
         
// 獲取父節點,並為它添加一個click事件
document.getElementById_x("parent-list").addEventListener("click",function(e) {
  // 檢查事件源e.targe是否為Li
    var target = getEventTarget(e);
  if(target && target .nodeName.toUpperCase == "LI") {
// 真正的處理過程在這里 console.log("List item ",e.target.id.replace("post-")," was clicked!"); } });
 
         

優點


通過上面的介紹,大家應該能夠體會到使用事件委托對於web應用程序帶來的幾個優點:
1.可以大量節省內存占用,減少事件注冊。
2.可以方便地動態添加和修改元素,不需要因為元素的改動而修改事件綁定。
3.JavaScript和DOM節點之間的關聯變少了,這樣也就減少了因循環引用而帶來的內存泄漏發生的概率。
缺點:
不是所有的事件都能冒泡的。blur、focus、load和unload不能像其它事件一樣冒泡。事實上blur和focus可以用事件捕獲而非事件冒泡的方法獲得(在IE之外的其它瀏覽器中)。
在管理鼠標事件的時候有些需要注意的地方。如果你的代碼處理mousemove事件的話你遇上性能瓶頸的風險可就大了,因為mousemove事件觸發非常頻繁。而mouseout則因為其怪異的表現而變得很難用事件代理來管理。
參考:http://www.cnblogs.com/silence516/archive/2009/09/03/delegateEvent.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM