亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

DOM中事件處理概覽與原理的全面解析

 更新時間:2016年08月16日 10:45:25   作者:蘇福  
這篇文章主要為大家詳細(xì)解析了DOM中事件處理概覽與原理,具有一定的參考價值,感興趣的小伙伴們可以參考一下

事件是一種異步編程的實現(xiàn)方式,本質(zhì)上是程序各個組成部分之間的通信,DOM支持大量的事件; 

本文通過這幾點向大家詳細(xì)解析事件處理的基本原理:事件類型、事件目標(biāo)、事件處理程序、事件對象、事件傳播

最后再向大家介紹Event對象; 

一、事件類型(event type):是一個用來說明發(fā)生了什么類型事件的全小寫的字符串,如‘mouseover'
傳統(tǒng)事件類型:表單事件,Window事件,鼠標(biāo)事件,鍵盤事件,DOM事件, HTML5事件,觸摸屏和移動設(shè)備事件等 

二、事件目標(biāo)(event target):觸發(fā)事件的對象 

三、事件處理程序(或事件監(jiān)聽程序)(event listener):處理或響應(yīng)事件的函數(shù)。當(dāng)某對象觸發(fā)某事件時,瀏覽器將自動調(diào)用在該對象上注冊的函數(shù);
注冊事件處理程序(監(jiān)聽事件):
1.作為HTML屬性注冊(只會在冒泡階段觸發(fā))如<table id="t" onclick="modifyText();">;而某些事件類型通常直接在瀏覽器上觸發(fā),而非任何特定文檔元素上觸發(fā),把這些事件處理程序放在<body>標(biāo)簽上,但瀏覽器會在Window對象上注冊它們,如<body onload="alert('Hello world!')">,這些事件有:
onafterprint onfocus ononline onresize onbeforeprint onhashchange 
onpagehide onstorage onbeforeunload onload onpageshow onundo 
onblur onmessage onpopstate onunload onerror onoffline onredo
作為HTML屬性的事件的值是JS代碼字符串,是處理函數(shù)的主體,不含{},注意:盡量不要在任何其他HTML標(biāo)簽上注冊事件,它違反了HTML與JavaScript代碼相分離的原則,倘若事件函數(shù)可能還沒加載進(jìn)來就點擊了事件對象元素,這會導(dǎo)致錯誤;

2.作為DOM元素的屬性來注冊(只會在冒泡階段觸發(fā)),此時的事件處理程序?qū)傩缘拿中杓印畂n'前綴,這種方式兼容所有瀏覽器,唯一的缺點是只能注冊一個事件處理函數(shù),如果定義兩次onclick屬性,后一次定義會覆蓋前一次;如:window.onload = function(){...};

3.除了IE8及之前版本外的所有瀏覽器中,DOM的事件操作(監(jiān)聽和觸發(fā)),都定義在EventTarget接口。Element節(jié)點、document節(jié)點和window對象,都部署了這個接口。此外,XMLHttpRequest、AudioNode、AudioContext等瀏覽器內(nèi)置對象,也部署了這個接口。該接口有三個方法,addEventListener和removeEventListener用于綁定和移除監(jiān)聽函數(shù),dispatchEvent用于觸發(fā)事件;
addEventListener(type,listener,boolean)方法來注冊listener,第三個參數(shù)設(shè)置事件的傳播方式,通常使用默認(rèn)值false,表示監(jiān)聽函數(shù)只在冒泡階段(pupple)被觸發(fā),當(dāng)設(shè)為true時,表示監(jiān)聽函數(shù)在捕獲階段(capture)觸發(fā);可以為同一對象上的同一類型事件注冊任意多個listener,所有l(wèi)istener會按照注冊順序觸發(fā)(注冊重復(fù)的listener將會被瀏覽器忽略);
如果希望向監(jiān)聽函數(shù)傳遞參數(shù),可以用匿名函數(shù)包裝一下監(jiān)聽函數(shù),如elm.addEventListener('click',function(){listen('實參')},false);
當(dāng)注冊的listener是一個對函數(shù)的引用變量,就可以用removeEventLestener(type,listener,boolean)在事件目標(biāo)上刪除該listener,對同一監(jiān)聽事件的冒泡事件和捕獲事件需要分別刪除,兩者互不干擾;

var div = document.getElementById('div');
var listener = function (event) {
 
           /* do something here */
        };
 div.addEventListener('click', listener, false);
 
div.removeEventListener('click', listener, false);

dispatchEvent(event)方法在當(dāng)前節(jié)點上手動觸發(fā)指定事件,從而觸發(fā)監(jiān)聽函數(shù)的執(zhí)行。該方法返回一個布爾值,只要有一個監(jiān)聽函數(shù)調(diào)用了Event.preventDefault(),就返回false,否則為true,參數(shù)是一個Event對象的實例,該參數(shù)不能為空,且必須是一個有效的事件對象,否則報錯;
btn.addEventListener('click', listener, false);
     var e = new Event('click');
btn.dispatchEvent(e); //在btn上立即觸發(fā)click事件,將立即調(diào)用listener 

下面例子根據(jù)dispatchEvent方法的返回值,判斷事件是否被取消了
var canceled = !btn.dispatchEvent(event);
if (canceled) { console.log('事件取消'); } 
else { console.log('事件未取消'); }} 

4.IE8及之前版本僅支持attachEvent (type,listener)和detachEvent(type,listener),它們的用法和addEventListener的區(qū)別:a.參數(shù)只有兩個;b.參數(shù)type必須加'on'前綴;c.它允許對同一監(jiān)聽事件進(jìn)行重復(fù)注冊,且都會被調(diào)用;d.使用attachEvent方法有個缺點,是this的值會變成 window 對象而不是觸發(fā)事件的元素;
調(diào)用順序問題:1).通過設(shè)置對象屬性或HTML屬性注冊的處理程序一直優(yōu)先調(diào)用;
                         2).使用addEventListener 注冊的處理程序按照它們的注冊順序調(diào)用;
                         3).舊版IE中使用attachEvent注冊的處理程序可能按照任何順序調(diào)用。
返回值問題:

1).事件處理程序的返回值只對通過屬性注冊的處理程序才有意義,通過設(shè)置對象屬性或HTML屬性注冊 事件處理程序的返回值為false,就是告訴瀏覽器不要執(zhí)行這個事件相關(guān)的默認(rèn)操作。當(dāng)瀏覽器要跳轉(zhuǎn)到新頁面時觸發(fā)Window對象的onbeforeunload事件,若它的的返回值為字符串,則它將出現(xiàn)在詢問確認(rèn)對話框中;

2).addEventListener()或attachEvent()注冊事件處理程序若要取消瀏覽器的默認(rèn)操作必須調(diào)用preventDefault()方法或設(shè)置事件對象的returnValue屬性。
this指向問題:

1).addEventListener方法指定的監(jiān)聽函數(shù),內(nèi)部的this對象總是指向觸發(fā)事件的那個節(jié)點;
2).IE8及以前的attachEvent方法注冊的事件處理函數(shù)的this指向全局對象;
以下寫法的this對象都指向Element節(jié)點。 
                    element.onclick = print;
                    element.addEventListener('click', print, false)
                    element.onclick = function () {console.log(this.id);}
                    <element onclick="console.log(this.id)">
 以下寫法的this對象,都指向全局對象。 
                    element.onclick = function (){ doSomething() }; 
                    element.setAttribute('onclick', 'doSomething()'); 
                    <element onclick="doSomething()"> 
                    element.attachEvent('onclick',doSomething) //IE8
內(nèi)存問題:對如下代碼,每個循環(huán)中都會創(chuàng)建一個新的匿名函數(shù),占用的內(nèi)存越來越多;由于沒有保持到匿名函數(shù)的引用,它不可能被調(diào)用 removeEventListener;所以應(yīng)當(dāng)把第二參數(shù)listener保持為對處理事件函數(shù)的引用;                  

 for(i=0 ; i<els.length ; i++){
   els[i].addEventListener("click", function(e){/*do something*/}, false});
 
    }

通用的兼容舊版IE的工具函數(shù):
確保事件處理程序的this指向事件的目標(biāo)對象的工具函數(shù)addEvent

 function addEvent(target,type,func){ 
  if(target.addEventListener){ 
    target.addEventListener(type,func,false);
 
  }else{
 
    target.attachEvent('on'+type,function(e){  //這里attachEvent注冊的處理函數(shù)未綁定引用,所以無法用detachEvent刪除
 
      return func.call(target,e);
 
    });
 
  }
 
}

通用的事件處理程序(因為IE8及以前版本,作為事件目標(biāo)的on-屬性的處理程序需要window.event來獲得事件對象,且觸發(fā)事件的目標(biāo)節(jié)點對象通過event.srcElement屬性獲得) 

function func(event){ 
  var event = event||window.event; 
  var target = event.target || event.srcElement; 
  //......處理程序代碼
 
}

四、事件傳播(event propagation):是瀏覽器決定哪個對象觸發(fā)其事件處理程序的過程。
“DOM2級事件”規(guī)定的事件流包括三個階段:事件捕獲階段==>處于目標(biāo)階段==>事件冒泡階段。首先發(fā)生的是事件捕獲階段(從外層向內(nèi)層傳播),為事件傳播經(jīng)過的所有節(jié)點截獲事件提供了機會。然后是實際的目標(biāo)接收事件(按注冊順序執(zhí)行)。最后一個階段是冒泡階段(從內(nèi)層向外層冒泡)。

當(dāng)容器元素及嵌套元素,即在捕獲階段又在冒泡階段調(diào)用事件處理程序時:事件按DOM事件流的順序執(zhí)行事件處理程序,且當(dāng)事件處于目標(biāo)階段時,事件調(diào)用順序決定于綁定事件的書寫順序

如果希望事件到某個節(jié)點為止,不再傳播,有兩種方式:

1.使用事件對象的event.stopPropagation()方法來阻止當(dāng)前監(jiān)聽函數(shù)的傳播;

2.使用事件對象的event.stopImmediatePropagation()方法來阻止當(dāng)前事件在其事件對象上的所有監(jiān)聽函數(shù)的傳播; 

事件的代理(delegation):由于事件會在冒泡階段向上傳播到父節(jié)點,因此可以把子節(jié)點的監(jiān)聽函數(shù)定義在父節(jié)點上,由父節(jié)點的監(jiān)聽函數(shù)統(tǒng)一處理多個子元素的事件;

五、事件對象(Event):事件發(fā)生以后,會生成一個事件對象,作為參數(shù)傳給監(jiān)聽函數(shù)。瀏覽器原生提供一個Event對象,所有的事件都是這個對象的實例,或者說繼承了Event.prototype對象。Event對象本身就是一個構(gòu)造函數(shù),可以用來生成新的實例。 

var ev = new Event("look", {"bubbles":true, "cancelable":false});
document.dispatchEvent(ev);

Event構(gòu)造函數(shù)接受兩個參數(shù)。第一個參數(shù)是字符串,表示事件的名稱;第二個參數(shù)是一個對象,表示事件對象的配置。該參數(shù)可以有以下兩個屬性。
bubbles:布爾值,可選,默認(rèn)為false,表示事件對象是否冒泡。
cancelable:布爾值,可選,默認(rèn)為false,表示事件是否可以被取消。 

Event對象的屬性:
1.與事件的階段有關(guān): 
bubbles: 只讀屬性,返回一個布爾值,表示當(dāng)前事件是否會冒泡,可根據(jù)事件是否會冒泡來調(diào)用不同的函數(shù)。 
eventPhase:返回一個整數(shù)值(0,1,2,3之一),表示事件目前所處的狀態(tài)
<0,事件目前沒有發(fā)生。
<1,事件目前處于捕獲階段,即處于從祖先節(jié)點向目標(biāo)節(jié)點的傳播過程中。該過程是從Window對象到Document節(jié)點,再到HTMLHtmlElement節(jié)點,直到目標(biāo)節(jié)點的父節(jié)點為止。
<2,事件到達(dá)目標(biāo)節(jié)點,即target屬性指向的那個節(jié)點。
<3,事件處于冒泡階段,即處于從目標(biāo)節(jié)點向祖先節(jié)點的反向傳播過程中。該過程是從父節(jié)點一直到Window對象。只有bubbles屬性為true時,這個階段才可能發(fā)生 

2.與事件的默認(rèn)行為有關(guān): 
cancelable:返回一個布爾值,表示事件是否可以取消。如果要取消某個事件,需要在這個事件上面調(diào)用preventDefault方法 
defaultPrevented:返回一個布爾值,表示該事件是否調(diào)用過preventDefault方法。

3.與事件的目標(biāo)節(jié)點有關(guān): 
currentTarget:返回事件執(zhí)行的監(jiān)聽函數(shù)所綁定的那個節(jié)點。 
target:返回觸發(fā)事件的那個節(jié)點。在IE6—IE8之中,該屬性的名字不是target,而是srcElement

4.與事件對象的其他信息相關(guān): 
type:返回一個字符串,表示事件類型 
detail:返回一個數(shù)值,表示事件的某種信息。具體含義與事件類型有關(guān),對于鼠標(biāo)事件,表示鼠標(biāo)按鍵在某個位置按下的次數(shù),比如對于dblclick事件,detail屬性的值總是2 
timeStamp:返回一個毫秒時間戳,表示事件發(fā)生的時間。從PerformanceTiming.navigationStart開始計算,即表示距離用戶導(dǎo)航至該網(wǎng)頁的時間。如果想將這個值轉(zhuǎn)為Unix紀(jì)元時間戳,就要計算event.timeStamp + performance.timing.navigationStart
isTrusted:返回一個布爾值,表示該事件是否可以信任。用處不大,不同瀏覽器的支持不一樣。

Event對象的方法: 
preventDefault():取消瀏覽器對當(dāng)前事件的默認(rèn)行為,該方法生效的前提是,事件的cancelable屬性為true,如果為false,則調(diào)用該方法沒有任何效果。 
stopPropagation():終止事件在傳播過程的捕獲、目標(biāo)處理或起泡階段進(jìn)一步傳播。調(diào)用該方法后,該節(jié)點上處理該事件的處理程序?qū)⒈徽{(diào)用,事件不再被分派到其他節(jié)點。注意:該方法不能阻止同一個 Document 節(jié)點上的其他事件句柄被調(diào)用,但是它可以阻止把事件分派到其他節(jié)點 
stopImmediatePropagation():阻止同一個事件的其他監(jiān)聽函數(shù)被調(diào)用,只要其中有一個監(jiān)聽函數(shù)調(diào)用了該方法,其他的監(jiān)聽函數(shù)就不會再執(zhí)行了。

參考鏈接: 
http://javascript.ruanyifeng.com/dom/event.html#toc31 
https://developer.mozilla.org/zh-CN/docs/Web/API 
JavaScript權(quán)威指南第六版

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論