JavaScript事件

事件流

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

  • 事件冒泡

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

  • 事件捕獲

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

  • DOM事件流

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

事件處理程序

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

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

  • HTML事件處理程序

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

  • DOM0級(jí)事件處理程序

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

  • DOM2級(jí)事件處理程序

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

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

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

  • IE事件處理程序

IE實(shí)現(xiàn)了和DOM類(lèi)似的兩個(gè)方法,attachEvent()和detachEvent()蜻底。這兩個(gè)方法接受相同的兩個(gè)參數(shù):事件處理程序名稱和事件處理程序函數(shù)你稚。由于IE8以及更早的版本只支持事件冒泡,所以通過(guò)attachEvent()添加的事件處理程序都會(huì)被添加到冒泡階段朱躺。
在IE中使用attachEvent()與使用DOM0級(jí)方法的主要區(qū)別在于事件處理程序的作用域刁赖。在使用DOM0級(jí)方法的時(shí)候,事件處理程序會(huì)在其所屬元素的作用域內(nèi)運(yùn)行长搀;在使用attachEvent()方法時(shí)候宇弛,作用域?yàn)槿肿饔糜颍虼藅his等于window源请,例如:

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

同時(shí)與addEventListener()類(lèi)似枪芒,也可以為一個(gè)元素添加多個(gè)事件處理程序。

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

為了跨瀏覽器的方式處理事件谁尸,不少開(kāi)發(fā)人員會(huì)使用能夠隔離瀏覽器差異的JavaScript庫(kù)舅踪。要保證處理事件的代碼能在大多數(shù)瀏覽器下一致運(yùn)行,只需要關(guān)注冒泡階段良蛮。
第一個(gè)要?jiǎng)?chuàng)建的方法是addHandler()抽碌,作用是根據(jù)情況分別使用DOM0級(jí)方法、DOM2級(jí)方法或者IE方法來(lái)添加事件决瞳。這個(gè)函數(shù)接受3個(gè)參數(shù):要操作的元素货徙、事件名稱和事件處理程序函數(shù)左权。與之相對(duì)應(yīng)的是removeHandler(),也接受相同的參數(shù)痴颊。

事件對(duì)象

在觸發(fā)DOM上的某個(gè)事件時(shí)候赏迟,會(huì)產(chǎn)生一個(gè)事件對(duì)象event,這個(gè)對(duì)象中包含著所有與事件有關(guān)的信息蠢棱。包括導(dǎo)致事件的元素锌杀、事件的類(lèi)型以及其他與特定事件相關(guān)的信息。所有瀏覽器都支持event對(duì)象泻仙,但是支持方式不同糕再。

  • DOM中的事件對(duì)象

兼容DOM的瀏覽器會(huì)將一個(gè)event對(duì)象傳入到事件處理程序中。無(wú)論指定事件處理程序時(shí)使用什么方法(DOM0級(jí)或DOM2級(jí))饰豺,都會(huì)傳入event對(duì)象。
例如

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

這兩個(gè)例子都會(huì)顯示事件的類(lèi)型允蜈,這個(gè)屬性始終都會(huì)包含被觸發(fā)的事件類(lèi)型冤吨。
在通過(guò)html特性指定事件處理程序時(shí),變量event中保存著event對(duì)象饶套,比如

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

這種方式提供event對(duì)象漩蟆,可以讓html特性事件處理程序與javascript函數(shù)執(zhí)行相同的操作
在事件處理程序內(nèi)部,對(duì)象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
};

這個(gè)例子檢驗(yàn)了currentTarget和target與this的值,由于click事件的目標(biāo)是按鈕构挤,因此這三個(gè)值是相等髓介。如果事件處理程序存在與按鈕的父節(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)單擊這個(gè)例子中的按鈕時(shí)候唐础,this和currentTarget都等于document.body,因?yàn)槭录幚淼某绦蚴亲?cè)到這個(gè)元素上的矾飞,但是target的元素卻等于按鈕元素一膨,是因?yàn)樗莄lick的真正目標(biāo)。
在需要通過(guò)一個(gè)函數(shù)處理多個(gè)事件的時(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ù)來(lái)處理3中不同的事件。這里可以通過(guò)檢測(cè)event.type屬性申眼,讓函數(shù)能夠確定發(fā)生了什么事件森篷,并且執(zhí)行相應(yīng)操作输钩。
要阻止特定事件默認(rèn)行為,可以使用preventDefault()方法仲智。但是只有cancelable屬性設(shè)置為true的事件买乃,才可以使用preventDefault()來(lái)取消默認(rèn)行為。
stopPropagation()方法用于立即停止事件在DOM層次中的傳遞钓辆,進(jìn)一步取消事件的捕獲或者冒泡剪验。同時(shí),事件對(duì)象的eventPhase屬性可以確定事件在當(dāng)前位置前联。

  • IE中的事件對(duì)象

與訪問(wèn)DOM中的event對(duì)象不同功戚,要訪問(wèn)IE中的event對(duì)象有幾種不同的方式,取決于指定事件處理程序的方法似嗤。在使用DOM0級(jí)方法添加事件處理程序時(shí)候啸臀,event作為window對(duì)象的一個(gè)屬性存在。

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

此時(shí)烁落,在通過(guò)window.event取得了event對(duì)象乘粒,并且檢測(cè)了被觸發(fā)事件的類(lèi)型∩怂可是如果事件處理程序利用的是attachEvent()添加的灯萍,那么就會(huì)有一個(gè)event對(duì)象作為參數(shù)被傳入事件處理程序函數(shù)中。

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

在類(lèi)似使用這樣的方法每聪,可以通過(guò)window對(duì)象來(lái)訪問(wèn)event對(duì)象旦棉,就像使用DOM0方法一樣。
由于事件處理程序的作用域是根據(jù)指定它的方式來(lái)確定的药薯,所以不能認(rèn)為this會(huì)始終等于事件目標(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
});

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

  • 跨瀏覽器中的事件對(duì)象

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

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)頁(yè)面完全加載后在window上觸發(fā),當(dāng)圖像加載完成后在img元素上觸發(fā)鄙煤,或當(dāng)嵌入內(nèi)容加載完成時(shí)晾匠,在object元素上觸發(fā)

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

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

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

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

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

scroll:用戶滾動(dòng)帶滾動(dòng)條的元素時(shí)梯刚,在該元素上觸發(fā)

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

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市澜共,隨后出現(xiàn)的幾起案子向叉,更是在濱河造成了極大的恐慌,老刑警劉巖嗦董,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件母谎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡京革,警方通過(guò)查閱死者的電腦和手機(jī)奇唤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)匹摇,“玉大人咬扇,你說(shuō)我怎么就攤上這事±炔” “怎么了懈贺?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)坡垫。 經(jīng)常有香客問(wèn)我梭灿,道長(zhǎng),這世上最難降的妖魔是什么葛虐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任胎源,我火速辦了婚禮棉钧,結(jié)果婚禮上屿脐,老公的妹妹穿的比我還像新娘。我一直安慰自己宪卿,他們只是感情好的诵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著佑钾,像睡著了一般西疤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上休溶,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天代赁,我揣著相機(jī)與錄音,去河邊找鬼兽掰。 笑死芭碍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的孽尽。 我是一名探鬼主播窖壕,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了瞻讽?” 一聲冷哼從身側(cè)響起鸳吸,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎速勇,沒(méi)想到半個(gè)月后晌砾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡快集,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年贡羔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片个初。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乖寒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出院溺,到底是詐尸還是另有隱情楣嘁,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布珍逸,位于F島的核電站逐虚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谆膳。R本人自食惡果不足惜叭爱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望漱病。 院中可真熱鬧买雾,春花似錦、人聲如沸杨帽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)注盈。三九已至晃危,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間老客,已是汗流浹背僚饭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胧砰,地道東北人鳍鸵。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像朴则,于是被迫代替她去往敵國(guó)和親权纤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钓简,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

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