事件

——《JavaScript高級程序設計》Chapter13學習筆記

1.事件處理程序

1.HTML事件處理程序

1)用法舉例

方法1:javascript

<input type="button" value="click me" onclick="alert('Clicked')"/>

方法2:css

<input type="button" value="click me" onclick="alert(&quot;Clicked&quot;)"/>

方法3:html

<input type="button" value="click me" onclick="showMessage()"/>
<script type="text/javascript">
    function showMessage() {
        alert("Clicked");
    }
</script>

2)獨到之處

(1)event和this

這樣指定事件處理程序會建立一個封裝着元素屬性值的函數。該該函數中有局部變量event對象和this(等於事件目標元素)值。java

<input type="button" value="click me" onclick="alert(event.type)"/> //彈出"click"

 <input type="button" value="click me" onclick="alert(this.value)"/>//彈出"click me"
(2)擴展做用域

先略chrome

3)缺點

  • 1.時差問題:用戶可能會在HTML元素一出現就在頁面觸發相應事件,但事件處理程序可能還不具有執行條件。以下改進:瀏覽器

    <input type="button" value="click me" onclick="try{showMessage();}catch(ex){}"/>
  • 2.做用域擴展事件處理程序的做用域鏈在不一樣瀏覽器中會致使不一樣結果。
  • 3.HTML與JavaScript代碼緊密耦合。app

2.DOM0級事件處理程序

  • 優點:(1)簡單;(2)跨瀏覽器
  • this:引用當前元素;即其是在當前元素的做用域運行。
  • 缺點:一個元素只能這樣添加一個事件處理程序。dom

    var btn=document.getElementById("myBtn");
      btn.onclick=function(){//添加事件處理程序
          alert(this.id);
      }
    
    
      btn.onclick=null;//取消事件處理程序

3.DOM2級事件處理程序

(1)添加事件處理程序:(Element).addEventListener(,,)

  • 優點:能夠添加多個事件處理程序,按順序觸發。函數

    var btn=document.getElementById("myBtn");
      btn.addEventListener("click",function(){
          alert(this.id)    
      },false);
      btn.addEventListener("click",function(){
          alert("Hello world");
      },false);

(2)移除事件處理程序:(Element).removeEventListener(,,)

直接傳入相同的函數代碼沒用,其實那是個徹底不一樣的函數:學習

var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
    alert(this.id)    
},false);
btn.removeEventListener("click",function(){
    alert("this.id");
},false);//沒用

得像這樣:

var btn=document.getElementById("myBtn");
var handler=function(){
    alert(this.id);
}
btn.addEventListener("click",handler,false);
btn.removeEventListener("click",handler,false);//有效

通常第三個參數都爲false(添加到冒泡階段),這樣能夠最大限度地兼容瀏覽器。

4.IE事件處理程序:attachEvent()、detachEvent()

var btn=document.getElementById("myBtn");
var handler=function(){
    alert("Clicked");
};
btn.attachEvent("onclick",handler);
btn.detachEvent("onclick",handler);

注意:

  • 1.其第一個參數帶on,DOM2級不帶on
  • 2.只有兩個參數,由於IE8及更早版本不支持捕獲,只支持冒泡
  • 3.事件處理程序的做用域是全局做用域,this爲window;而DOM0、DOM2事件處理程序做用域是其元素的做用域。

    var btn=document.getElementById("myBtn");
     var handler=function(){
         alert(this===window);//true
     };
     btn.attachEvent("onclick",handler);
  • 4.attachEvent()也能夠爲一個元素添加多個事件處理程序。與DOM2不一樣,這些事件處理程序是以相反的順序觸發。
  • 5.用detachEvent()時與DOM2方法同樣,第二個參數不能是匿名函數,只能採用相同函數的引用。

5.跨瀏覽器的事件處理程序

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;
        }
    }    
}

應用:

var btn=document.getElementById("myBtn");
var handler=function(){
    alert("Hello world");
}
EventUtil.addHandler(btn,"click",handler);

缺陷:沒有考慮全部的瀏覽器問題,如IE做用域的問題。

2.事件對象

1.DOM中的事件對象

方法/屬性名稱 類別 做用
preventDefault() Function 取消事件的默認行爲。在cancelable是true的時候能夠用這個方法。
stopImmediatePropagation() Function 取消事件冒泡同時阻止當前節點上的事件處理程序被調用。
stopPropagation() Function 取消事件的進一步捕獲或冒泡,對當前節點無影響。在bubbles是true的時候能夠用這個方法。
target Element 事件真正的具體的目標
currentTarget Element 被事件處理程序註冊的元素
bubbles Boolean 事件是否能夠冒泡
cancelable Boolean 是否能夠取消事件默認行爲
type String 被觸發的事件的類型
eventPhase Integer 調用事件處理的階段:一、二、3(捕獲、目標、冒泡)

(1)this/currentTarget/target:區別

  • this始終等於currentTarget爲綁定了事件處理程序的元素,target爲實際的目標元素
  • 若是直接將事件處理程序綁定給了實際的目標元素,則this/currentTarget/target三者相同。

爲目標元素綁定事件處理程序:

var btn=document.getElementById("myBtn");

btn.onclick=function(event){
    console.log(this===event.target);//true
    console.log(this===event.currentTarget);//true
    console.log(this===btn);//true
}

爲非目標元素綁定事件處理程序:

var btn=document.getElementById("myBtn");
document.body.onclick=function(event){
    console.log(this===event.target);//false
    console.log(this===document.body);//true
    console.log(event.target===btn);//true
}

(2)event.type屬性:在一個函數要處理多個事件時使用

var btn=document.getElementById("myBtn");

var handler=function(event){
    switch (event.type) {
        case "click":
            alert("Clicked");
            break;
        case "mouseover":
            event.target.style.setProperty("background-color","red");
            break;
        case "mouseout":
            event.target.style.removeProperty("background-color");
            break;
    }
};
btn.onclick=handler;
btn.onmouseover=handler;
btn.onmouseout=handler;

(3)preventDefault()方法

例如:a元素默認行爲是點擊時導航到指定URL,這樣能夠阻止

link.onclick=function(event){
    event.preventDefault();
}

(4)stopPropagation()方法

當即中止事件在DOM層次的傳播。以下能夠避免觸發document.body上的事件處理程序。

var btn=document.getElementById("myBtn");

btn.onclick=function(event){
    alert("clicked");
    event.stopPropagation();
}
document.body.onclick=function(event){
    alert("Body clicked");
}

(5)eventPhase屬性

var btn=document.getElementById("myBtn");

btn.onclick=function(event){
    alert(event.eventPhase);
}//2
document.body.addEventListener("click",function(event){
    alert(event.eventPhase);
},true);//1
document.body.addEventListener("click",function(event){
    alert(event.eventPhase);
},false);//3

2.IE中的事件對象

方法/屬性名稱 類別 做用
cancelBubble Boolean 默認爲false,設置爲true能夠取消事件冒泡(與DOM的stopPropagation()方法做業相同)
returnValue Boolean 默認爲true,設置爲false能夠取消事件的默認行爲(與DOM的preventDefault()方法做用相同)
srcElement Element 事件的真正的具體的目標(與DOM的target屬性做用相同)

3.跨瀏覽器的事件處理對象

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;
    },
    preventDefault:function(event){
        if (event.preventDefault) {
            event.preventDefault();
        }
        else{
            event.returnValue=false;
        }
    },
    getTarget:function(event){
        return event.target?event.target:event.srcElement;
    },
    stopPropagation:function(event){
        if (event.stopPropagation) {
            event.stopPropagation();
        }
        else{
            event.cancelBubble=true;
        }
    }
};

EventUtil對象使用例子:

var link=document.getElementById("mylink");

EventUtil.addHandler(link,"click",function(event){
    event=EventUtil.getEvent(event);
    EventUtil.preventDefault(event);
    target=EventUtil.getTarget(event);
    alert(target.tagName);
});

3.事件類型

1.UI事件

不必定與用戶操做有關的事件。

1)load事件

簡介:

當頁面徹底加載後(包括全部圖像、JavaScript文件、CSS文件等外部資源),就會觸發window上面的load事件。

此時爲該事件處理程序傳入的event對象不包含有關這個事件的任何附加信息。只有在兼容DOM的瀏覽器中,event.target屬性被設置爲document。

綁定方法:

方法一:

EventUtil.addHandler(window,"load",function(event){
    alert("loaded"); 
})

方法二:

<body onload="alert('loaded')">//只能爲body添加onload屬性,不能如方法一那樣爲body綁定load事件
···
<\body>
應用
(1)動態建立img後確認是否加載完畢
EventUtil.addHandler(window,"load",function(){
    var image=document.createElement("img");
    EventUtil.addHandler(image,"load",function(event){
        event=EventUtil.getEvent(event);
        var target=EventUtil.getTarget(event);
        alert(target.src);
    });
    document.body.appendChild(image);
    image.src="news.png";
})

注意:

  • window要首先綁定onload事件處理程序。由於向DOM中添加新元素的話必須保證頁面已經加載完畢。若是在頁面加載完畢前操做document.body會致使錯誤
  • 新圖像元素不必定從添加到文檔後纔開始下載,而是一旦設置src就會下載,故得在指定src屬性以前先指定事件
(2)動態建立script後確認是否加載完畢
EventUtil.addHandler(window,"load",function(){//該處括號內寫上event也沒事
    var script=document.createElement("script");
    EventUtil.addHandler(script,"load",function(event){
        alert("loaded");
    });
    script.src="test2.js";
    document.body.appendChild(script);
})
  • 與圖像不一樣,只有在設置了src元素並將其添加到文檔以後纔會開始下載JS文件,故指定src和事件處理程序的前後順序隨意。
(3)動態建立樣式後確認是否加載完畢
EventUtil.addHandler(window,"load",function(event){
   var link=document.createElement("link");
   link.type="text/css";
   link.rel="stylesheet";
   EventUtil.addHandler(link,"load",function(event){
        alert("loaded");
   });
   link.href="test1.css";
   document.getElementsByTagName("head")[0].appendChild(link);
   
});
  • 與圖像不一樣,與script相似,只有在設置了href屬性並將其添加到文檔以後纔會開始下載樣式表。故綁定事件處理程序和設置href的順序隨意。

2)unload事件

簡介

在文檔徹底被卸載時觸發

3)resize事件

簡介

當瀏覽器窗口被調整到一個新的高度或寬度時觸發。IE、Safari、Chrome、Opera會在窗口變化了1像素時就觸發resize事件。Firefox在用戶中止調整窗口大小時才觸發resize。

EventUtil.addHandler(window,"resize",function(event){
   alert("resized");
});

4)scroll事件

簡介

在window對象上發送,實際表示頁面中相應元素的變化。可用scrollLeft和scrollTop來監控這一變化。

EventUtil.addHandler(window,"scroll",function(event){
   if (document.compatMode=="CSS1Compat") {//標準模式用document.documentElement
        alert(document.documentElement.scrollTop);
   }
   else{//"backMode"混雜模式用document.body
        alert(document.body.scrollTop);
   }
});

2.焦點事件

1)blur事件:

在元素失去焦點時觸發。不冒泡。

2)focus事件:

在元素得到焦點時觸發。不冒泡。

3)focusin事件:

在元素得到焦點時觸發。與focus等價,但它冒泡。

4) focusout事件:

在元素失去焦點時觸發。是blur的通用版,但它冒泡。

注意:
focusin/focusout支持瀏覽器是IE5.5+、Safari5.1+、Opera11.5+和Chrome;另有相同做用的DOMFocusIn/DOMFocusOut,只有Opera支持。

3.鼠標與滾輪事件

1)經常使用鼠標事件

簡介
事件名稱 簡介
click 單擊鼠標左鍵或按下回車觸發
dbclick 雙擊鼠標左鍵觸發
mousedown 用戶按下任意鼠標按鈕時觸發
mouseup 用戶釋放鼠標按鈕時觸發
mouseover 用戶首次將鼠標從一個元素移入另外一個元素邊界以內時觸發
mouseout 用戶將鼠標從一個元素移入另外一個元素時觸發,另外一個元素可能位於前一個元素的內部或外部、子元素
mouseenter 在鼠標光標從元素外部首次移動到元素範圍以內(包括其子元素)時觸發。不冒泡。
mouseleave 在位於元素上方的鼠標光標移動到元素範圍以外時觸發(移到後代元素上不觸發)。不冒泡。
注意:
  • 除mouseenter,mouseleave不冒泡,其餘都冒泡
  • 幾個相關事件的觸發順序:
    1. mousedown
    2. mouseup
    3. click
    4. mousedown
    5. mouseup
    6. click
    7. dbclick

2)幾種座標位置

(1)光標視口位置:event.clientX/clientY

表示事件發生時,鼠標光標在視口中的水平和垂直座標。注意:其不包括頁面滾動距離。

EventUtil.addHandler(document.body,"click",function(event){
    event=EventUtil.getEvent(event);
    alert("clientX:"+event.clientX+" clientY:"+event.clientY);
})
(2)光標頁面位置:event.pageX/pageY

表示事件發生時,鼠標光標在頁面中的位置。注意:其實從頁面自己計算座標而非視口。

EventUtil.addHandler(document.body,"click",function(event){
    event=EventUtil.getEvent(event);
    alert("pageX:"+event.pageX+" pageY:"+event.pageY);
})
(3)屏幕座標位置:event.screenX/screenY
EventUtil.addHandler(document.body,"click",function(event){
    event=EventUtil.getEvent(event);
    alert("screenX:"+event.screenX+" screenY:"+event.screenY);
})

3)修改鍵屬性:event.shiftKey/ctrlKey/altKey/metaKey

這些鍵經常被用來修改鼠標事件的行爲,對應四個屬性表示修改鍵的狀態:shiftKey,ctrlKey,altKey,metaKey。鍵被按下,則值爲true;不然爲false。

var btn=document.getElementById("myBtn");
EventUtil.addHandler(btn,"click",function(event){
    event=EventUtil.getEvent(event);
    var keys=new Array();
    
    if (event.shiftKey) {
        keys.push("shift");
    }
    if (event.ctrlKey) {
        keys.push("ctrl");
    }
    if (event.altKey) {
        keys.push("alt");
    }
    if (event.metaKey) {
        keys.push("meta");
    }
    alert("Keys:"+keys.join(","));
    
})

4)相關元素

  • 對mouseover而言:事件主目標是得到光標的元素,相關元素是失去光標的元素。
  • 對mouseout而言:事件主目標是失去光標的元素,修改元素是得到光標的元素。

相關元素爲:event.relatedTarget屬性(DOM),event.fromElement/toElement(IE)

兼容性代碼:

var EventUtil={
    ···
     getRelatedTarget: function(event){
        if (event.relatedTarget) {
            return event.relatedTarget;
        }
        else if(event.fromElement) {
            return event.fromElement;
        }
        else if(evnet.toElement){
            return event.toElement;
        }
        else{
            return null;
        }
    }
}

5)鼠標按鈕屬性:event.button

對於mousedown和mouseup事件來講,其具備event.button屬性。
DOM的event.button可爲:

  • 0:左鍵
  • 1:中間滾輪
  • 2:右鍵

IE較複雜

6)鼠標滾輪事件:

(1)mousewheel事件(IE/Opera/Chrome/Safari)

可檢測器event.wheelData屬性,該屬性是120的倍數(正數表向前滾,負數表向後滾,Opera中正負號顛倒)。

EventUtil.addHandler(document,"mousewheel",function(event){
    event=EventUtil.getEvent(event);
    alert(event.wheelData);
})
(2)DOMMouseScroll事件(FireFox)

與mousewheel事件相似,對應信息保存在detail屬性中,爲3的倍數(正數表向前滾,負數表向後滾)。

相關文章
相關標籤/搜索