JavaScript事件

事件流

事件流描述的是從頁面中接受事件的順序。但是IE和Netscape開發(fā)團(tuán)隊(duì)提出了差不多相反的事件流的概念。IE的事件流是事件冒泡,而Netescape Communicator的事件流是事件捕獲。

  • 事件冒泡

IE的事件流叫做事件冒泡,即事件開始時由最具體的元素(文檔中嵌套層次最深的那個節(jié)點(diǎn))接收,然后逐級向上傳播到較為不具體的節(jié)點(diǎn)。

  • 事件捕獲

事件捕獲的思想是不太具體的節(jié)點(diǎn)應(yīng)該更早接受到事件,而最具體的節(jié)點(diǎn)應(yīng)該最后接收到事件。事件捕獲的泳衣在于事件到達(dá)預(yù)定目標(biāo)前捕獲它。
但是由于老版本不支持,因此很少有人用事件捕獲,在特殊時候再利用事件捕獲,一般都可以利用事件冒泡。

  • DOM事件流

"DOM2級事件"規(guī)定的事件流包括了三個階段:事件捕獲階段、處于目標(biāo)階段和事件冒泡階段。首先發(fā)生的是事件捕獲,為截獲事件提供了機(jī)會。然后是世紀(jì)的目標(biāo)接收到事件。最后一個階段是冒泡階段,可以在這個階段對事件做出響應(yīng)。
在DOM的事件流中,實(shí)際的目標(biāo)在捕獲階段不會接收到事件。下一個階段是處于目標(biāo)階段,于是事件在目標(biāo)上發(fā)生,并且在事件處理中看作是冒泡階段的一部分。然后冒泡階段發(fā)生,事件又傳播回文檔。

事件處理程序

事件處理就是用戶或者瀏覽器自身執(zhí)行的某種動作。例如click、load和mouseover等,都是事件的名字。而響應(yīng)某個事件的函數(shù)就叫做事件處理程序,也叫做事件偵聽器。

為事件指定的處理程序有如下幾種:

  • HTML事件處理程序

某個元素支持的每種事件,都可以使用一個與相應(yīng)事件處理程序同名的HTML特性來指定的。這個特性的值應(yīng)該是能夠執(zhí)行JavaScript代碼。

  • DOM0級事件處理程序

通過JavaScript指定事件處理程序的傳統(tǒng)方式,就是將一個函數(shù)賦值給一個事件處理程序?qū)傩?。這種為事件處理程序賦值的方法是在第四代Web瀏覽器中出現(xiàn)的,而且至今仍然為所有現(xiàn)代瀏覽器所支持。要使用JavaScript指定事件處理程序,首先必須取得一個要操作的對象的引用。

  • DOM2級事件處理程序

"DOM2"事件定義了兩個方法,用于處理指定和刪除事件處理程序的操作:addeventListener()和removeEventListener()。所有DOM節(jié)點(diǎn)中都包含這兩個方法,并且它們都接受3個參數(shù):要處理的事件名、作為事件處理程序的函數(shù)和一個布爾值。如果最后這個布爾值參數(shù)是true,表示在捕獲階段調(diào)用事件處理程序;如果是false,表示在冒泡階段調(diào)用事件處理程序。
比如要在按鈕上為click事件添加事件處理程序,可以使用以下代碼:

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

此事件會在冒泡階段被觸發(fā),此時和DOM0級方法一樣,這里添加的事件處理程序也是其依附的元素的作用域中運(yùn)行。使用DOM2級添加方法的主要好處是能夠添加多個事件處理程序。

  • IE事件處理程序

IE實(shí)現(xiàn)了和DOM類似的兩個方法,attachEvent()和detachEvent()。這兩個方法接受相同的兩個參數(shù):事件處理程序名稱和事件處理程序函數(shù)。由于IE8以及更早的版本只支持事件冒泡,所以通過attachEvent()添加的事件處理程序都會被添加到冒泡階段。
在IE中使用attachEvent()與使用DOM0級方法的主要區(qū)別在于事件處理程序的作用域。在使用DOM0級方法的時候,事件處理程序會在其所屬元素的作用域內(nèi)運(yùn)行;在使用attachEvent()方法時候,作用域?yàn)槿肿饔糜?,因此this等于window,例如:

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
    console.log(this === window) // true
})

同時與addEventListener()類似,也可以為一個元素添加多個事件處理程序。

  • 跨瀏覽器的事件處理程序

為了跨瀏覽器的方式處理事件,不少開發(fā)人員會使用能夠隔離瀏覽器差異的JavaScript庫。要保證處理事件的代碼能在大多數(shù)瀏覽器下一致運(yùn)行,只需要關(guān)注冒泡階段。
第一個要創(chuàng)建的方法是addHandler(),作用是根據(jù)情況分別使用DOM0級方法、DOM2級方法或者IE方法來添加事件。這個函數(shù)接受3個參數(shù):要操作的元素、事件名稱和事件處理程序函數(shù)。與之相對應(yīng)的是removeHandler(),也接受相同的參數(shù)。

事件對象

在觸發(fā)DOM上的某個事件時候,會產(chǎn)生一個事件對象event,這個對象中包含著所有與事件有關(guān)的信息。包括導(dǎo)致事件的元素、事件的類型以及其他與特定事件相關(guān)的信息。所有瀏覽器都支持event對象,但是支持方式不同。

  • DOM中的事件對象

兼容DOM的瀏覽器會將一個event對象傳入到事件處理程序中。無論指定事件處理程序時使用什么方法(DOM0級或DOM2級),都會傳入event對象。
例如

var btn = document.getElementById("myBtn");
btn.onclick = function(event){
    console.log(event.type); // "click"
};
btn.addEventListener("click", function(){
    console.log(event.type); // "click"
}, false);

這兩個例子都會顯示事件的類型,這個屬性始終都會包含被觸發(fā)的事件類型。
在通過html特性指定事件處理程序時,變量event中保存著event對象,比如

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

這種方式提供event對象,可以讓html特性事件處理程序與javascript函數(shù)執(zhí)行相同的操作
在事件處理程序內(nèi)部,對象this始終等于currentTarget的值,而target則只包含事件的實(shí)際目標(biāo)。如果直接將事件處理程序指定給了目標(biāo)元素,則this、currentTarget和target包含相同的值。比如

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

這個例子檢驗(yàn)了currentTarget和target與this的值,由于click事件的目標(biāo)是按鈕,因此這三個值是相等。如果事件處理程序存在與按鈕的父節(jié)點(diǎn)中(例如document,body中)那么這些值是不相等的。如下例子

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

當(dāng)單擊這個例子中的按鈕時候,this和currentTarget都等于document.body,因?yàn)槭录幚淼某绦蚴亲缘竭@個元素上的,但是target的元素卻等于按鈕元素,是因?yàn)樗莄lick的真正目標(biāo)。
在需要通過一個函數(shù)處理多個事件的時候,可以使用type屬性。例如

var btn = document.getElementById("myBtn");
var handler = function(event){
  switch(event.type){
    case "click":
      console.log("Clicked");
      break;

    case "mouseover":
      event.target.style.backgroundColor = "red";
      break;

    case "mouseout":
      event.target.style.backgroundColor = "";
      break;
    }
};

btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;

利用handler函數(shù)來處理3中不同的事件。這里可以通過檢測event.type屬性,讓函數(shù)能夠確定發(fā)生了什么事件,并且執(zhí)行相應(yīng)操作。
要阻止特定事件默認(rèn)行為,可以使用preventDefault()方法。但是只有cancelable屬性設(shè)置為true的事件,才可以使用preventDefault()來取消默認(rèn)行為。
stopPropagation()方法用于立即停止事件在DOM層次中的傳遞,進(jìn)一步取消事件的捕獲或者冒泡。同時,事件對象的eventPhase屬性可以確定事件在當(dāng)前位置。

  • IE中的事件對象

與訪問DOM中的event對象不同,要訪問IE中的event對象有幾種不同的方式,取決于指定事件處理程序的方法。在使用DOM0級方法添加事件處理程序時候,event作為window對象的一個屬性存在。

var btn = document.getElementById("myBtn");
btn.onclick = function(){
    var event = window.event;
    console.log(event.type);  //"click"
}

此時,在通過window.event取得了event對象,并且檢測了被觸發(fā)事件的類型??墒侨绻录幚沓绦蚶玫氖莂ttachEvent()添加的,那么就會有一個event對象作為參數(shù)被傳入事件處理程序函數(shù)中。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(event){
    console.log(event.type); //"click"
});

在類似使用這樣的方法,可以通過window對象來訪問event對象,就像使用DOM0方法一樣。
由于事件處理程序的作用域是根據(jù)指定它的方式來確定的,所以不能認(rèn)為this會始終等于事件目標(biāo)。比如

var btn = document.getElementById("myBtn");
btn.onclick = function(){
    console.log(window.event.srcElement === this); //true
}
btn.attachEvent("onclick", function(){
    console.log(event.srcElement === this ); //false
});

第一個事件處理程序中(使用DOM0級方法指定的)srcElement屬性等于this,但是第二個事件處理程序中,這二者值并不相同

  • 跨瀏覽器中的事件對象

IE中event對象的全部信息和方法DOM中都有,只不過實(shí)現(xiàn)方式不一樣。不過可以基于其相似性,可以寫出跨瀏覽器的事件對象方案。

function getEvent(e) {
    return e || window.event;
}

function getTarget(e) {
    return e.target || e.scrElement;
}

function preventDefault(e) {
    if (e.preventDefault)
        e.preventDefault();
    else
        e.returnValue = false;
}

function stopPropagation(e) {
    if (e.stopPropagation)
        e.stopPropagation();
    else
        e.cancelBubble = true;
}

常用的HTML事件


load:當(dāng)頁面完全加載后在window上觸發(fā),當(dāng)圖像加載完成后在img元素上觸發(fā),或當(dāng)嵌入內(nèi)容加載完成時,在object元素上觸發(fā)

unload:頁面完全卸載后在window上觸發(fā),或嵌入內(nèi)容卸載后在object元素觸發(fā)

select:用戶選擇文本框中的字符時觸發(fā)

change:文本框焦點(diǎn)變化后其值改變時觸發(fā)

submit:用戶提交表單的時候觸發(fā)

resize:窗口或框架大小變化的時候在window上觸發(fā)

scroll:用戶滾動帶滾動條的元素時,在該元素上觸發(fā)

focus:頁面或元素獲得焦點(diǎn)時在window及相應(yīng)元素上觸發(fā)

blur:頁面或元素失去焦點(diǎn)時在window及相應(yīng)元素上觸發(fā)

beforeunload:頁面卸載前在window上觸發(fā)

mousewheel:不算HTML的,當(dāng)用戶通過鼠標(biāo)滾輪與頁面交互,在垂直方向滾動頁面時觸發(fā)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 事件處理程序在應(yīng)用中是必不可少的,雖然現(xiàn)在很多框架都有自己實(shí)現(xiàn)事件處理方法,但是熟知原生才能讓我們應(yīng)對各種各樣的需...
    俗三瘋閱讀 364評論 0 1
  • JavaScript與HTML之間的交互是通過事件完成的。可以使用事件偵聽器來預(yù)訂事件,正在傳統(tǒng)軟件工程中被稱為觀...
    yohn閱讀 218評論 1 1
  • 一.事件 事件是用戶或?yàn)g覽器自身執(zhí)行的某種動作,這是我自己的理解。 二.事件流 事件流描述的是從頁面中接收事件的順...
    卓三陽閱讀 2,296評論 1 2
  • 事件流 事件冒泡 IE的事件流叫做事件冒泡,即事件開始時由具體的元素接收,然后逐級向上傳播到較為不具體的節(jié)點(diǎn)。 事...
    soso101閱讀 264評論 0 1
  • 一、事件流 1.1 事件流 事件流:從頁面中接受事件的順序 事件冒泡:即事件開始時由最具體的元素(文檔中嵌套層次最...
    范小飯_閱讀 1,156評論 1 9

友情鏈接更多精彩內(nèi)容