日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

彻底理解H5的DOM事件

發(fā)布時間:2025/5/22 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 彻底理解H5的DOM事件 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我們大家都知道,人與人之間的交流可以通過語言,文字,肢體動作,面部微表情等,但是你知道Javascript和HTML之間是通過什么進行交互的么?你又知道Javascript和HTML之間是如何進行交互的么?如果你不是那么清楚,可以看這篇文章。。。

前面的話:

這篇博文由淺入深,先介紹兩種事件流,然后介紹常見的事件處理程序以及它們之間的差異(涉及到一個簡單的兼容的處理函數(shù)),后面還會針對事件對象進行深入學習,最后則是通過DOM事件實現(xiàn)的小案例。

事件流:

關于事件流,簡單的來說就是:事件流描述的是從頁面中接受事件的順序。下面是《Javascript高級程序設計》里面的說法:

當瀏覽器發(fā)展到第四代時(IE4和Netscape Communicator 4),瀏覽器團隊遇到一個很有意思的問題:頁面的哪一部分會擁有特定的事件?想象下在一張紙上有一組同心圓,如果你把手指放在圓心上,那么你的手指指向的不是一個圓,而是一組圓。兩家公司的開發(fā)團隊在看待瀏覽器事件方面還是一致的。如果你單擊了某個按鈕,那么同時你也單擊了按鈕的容器元素,甚至整個頁面。

事件流描述的是從頁面中接受事件的順序。但有意思的是,IE和Netscape開發(fā)團隊居然提出了兩個截然相反的事件流概念。IE的事件流是事件冒泡流,而Netscape的事件流是事件捕獲流。

事件冒泡

IE的事件流叫做事件冒泡,即事件開始時由最具體的元素接受,然后逐級向上傳播到較為不具體的節(jié)點。看下面的例子

<!DOCTYPE html> <html><head><meta charset="UTF-8"><title>事件流</title></head><body><input type="button" id="btn" value="" /></body> </html>

點擊按鈕,那么這個click事件會按照這樣傳播:
<input-->body-->html-->document

事件捕獲

Netscape團隊提出的另一種事件流叫做事件捕獲。事件捕獲的思想是不太具體的DOM節(jié)點應該更早接收到事件,而最具體的節(jié)點應該最后接收到事件。

針對上面同樣的例子,點擊按鈕,那么此時click事件會按照這樣傳播:
document-->html-->body-->input

雖然事件捕獲是Netscape唯一支持的事件流模型,但IE9、Safari、Chrome、Opera和Firefox目前也都支持這種事件流模型。但由于老版本的瀏覽器不支持,因此很少有人使用事件捕獲。

事件處理程序

HTML事件處理程序

HTML事件處理程序(現(xiàn)在不建議使用了):事件直接加在HTML代碼中,例如:

<input type="button" id="btn" value="HTML事件處理程序" οnclick="alert('HTML事件處理程序')" />

或者:

<input type="button" id="btn1" value="HTML事件處理程序" οnclick="demo1()" /> function demo1(){alert("HTML事件處理程序"); }

缺點:HTML和js代碼高耦合,如果修改,就要修改兩個地方--HTML元素內(nèi)和script函數(shù)。

DOM0級事件處理程序

DOM0級事件處理程序,是一種較傳統(tǒng)的方式:把一個函數(shù)賦值給一個事件的處理程序?qū)傩浴@?#xff1a;

var btn2 = document.getElementById("btn2"); btn2.onclick = function(){alert("DOM0級事件處理程序"); }

現(xiàn)在用得比較多,優(yōu)勢是簡單(只需要考慮JS不考慮HTML)且跨瀏覽器。如果想取消點擊事件,將其設為null即可。

var btn2.onclick = null;//這時點擊不會彈出窗口,表示已經(jīng)取消了該點擊事件

下面是我學習時候的一些思考:

思考一:DOM0級事件是否可以同時添加多個不同事件處理方法

var btn2 = document.getElementById("btn2"); btn2.onclick = function(){console.log("DOM0級事件處理程序-click-01"); } btn2.onmouseover = function(){console.log("DOM0級事件處理程序-mouseover"); }

結(jié)果:鼠標經(jīng)過,控制臺出現(xiàn):DOM0級事件處理程序-mouseover;鼠標點擊,控制臺出現(xiàn):DOM0級事件處理程序-click-01。
說明:DOM0級事件可以同時添加多個不同事件處理方法

思考二:DOM0級事件是否可以同時添加多個相同事件處理方法

我們在前面的基礎上添加如下代碼:

btn2.onclick = function(){console.log("DOM0級事件處理程序-click-02"); }

結(jié)果:鼠標經(jīng)過,控制臺出現(xiàn):DOM0級事件處理程序-mouseover;鼠標點擊,控制臺出現(xiàn):DOM0級事件處理程序-click-02。(在這里你可能以為會出現(xiàn)DOM0級事件處理程序-click-01和DOM0級事件處理程序-click-02)
說明:DOM0級事件不可以同時添加多個相同事件處理方法(這樣說好像不太嚴格,大概意思就是直接忽略了前面的onclick,只顯示最后的onclick的結(jié)果。
那么這里就設下一個疑問:我們應該如何讓DOM同時綁定多個相同事件呢???我們接著往下看

DOM2級事件處理程序

DOM2級事件處理程序定義了兩個方法--用于處理指定和刪除事件處理程序的操作:

  addEventListener()添加事件監(jiān)聽程序

  removeEventListener()移除事件監(jiān)聽程序

  三個參數(shù)設置;事件名稱,處理方法(函數(shù)),布爾值--false:表示在冒泡階段調(diào)用事件處理程序(可以最大限度的兼容瀏覽器),一般設為false;true表示在捕獲階段調(diào)用事件處理程序

來看下面的例子:

var btn3 = document.getElementById("btn3"); btn3.addEventListener('click',function(){console.log("DOM2級事件處理程序-click-01"); },false) //DOM2級事件處理程序-click-01

與DOM0級不同的是,我們移除需要使用removeEventListener(),代碼如下:

var btn3 = document.getElementById("btn3"); btn3.addEventListener('click',function(){console.log("DOM2級事件處理程序-click-01"); },false) btn3.removeEventListener('click',function(){console.log("DOM2級事件處理程序-click-移除成功"); },false) //DOM2級事件處理程序-click-01

在這里,你很有可能和我想的一樣,DOM2級事件處理程序已經(jīng)移除完了。但是結(jié)果是DOM2級事件處理程序-click-01依然還在,按照理論上來說不應該是被移除了么?但是為什么還在?

原因:通過addEventListener方法添加的事件處理程序只能用removeEventListener來移除,移除時傳入的參數(shù)與添加處理程序時使用的參數(shù)相同。這就意味著通過addEventListener添加的匿名函數(shù)將無法移除。真的是這樣么?我們繼續(xù)來看例子:

var btn3 = document.getElementById("btn3"); var handler = function demo3(){alert("DOM2級事件處理程序"); } btn3.addEventListener('click',handler,false) //在不加后面的代碼的時候彈框顯示DOM2級事件處理程序 btn3.removeEventListener('click',handler,false) //加了removeEventListener后點擊,沒有彈框,說明該點擊事件已經(jīng)被移除了

接下來我們同樣思考幾個問題:
思考一:DOM2級事件是否可以同時添加多個不同事件處理方法

var btn3 = document.getElementById("btn3"); btn3.addEventListener('click',function(){console.log("DOM2級事件處理程序-click-01"); },false) btn3.addEventListener('mouseover',function(){console.log("DOM2級事件處理程序-mouseover"); },false)

結(jié)果:鼠標經(jīng)過,控制臺出現(xiàn):DOM2級事件處理程序-mouseover;鼠標點擊,控制臺出現(xiàn):DOM2級事件處理程序-click-01。
說明:DOM2級事件可以同時添加多個不同事件處理方法

思考二:DOM2級事件是否可以同時添加多個相同事件處理方法

var btn3 = document.getElementById("btn3"); btn3.addEventListener('click',function(){console.log("DOM2級事件處理程序-click-01"); },false) btn3.addEventListener('mouseover',function(){console.log("DOM2級事件處理程序-mouseover"); },false) btn3.addEventListener('click',function(){console.log(this.id); },false)

結(jié)果:鼠標經(jīng)過,控制臺出現(xiàn):DOM2級事件處理程序-mouseover;鼠標點擊,控制臺出現(xiàn):DOM2級事件處理程序-click-01和btn3。
說明:DOM2級事件可以同時添加多個不同事件處理方法,同時在這里可以用this引用被觸發(fā)的元素。

注意:
  1、要處理的事件名(事件名去掉“on”,如點擊事件需寫成click);
  2、作為事件處理程序的函數(shù)名(函數(shù)不需要帶括號,只要函數(shù)名或者直接寫函數(shù)體也可以);
  3、布爾值(true表示使用事件捕獲流,false表示使用事件冒泡流,一般使用false兼容各種瀏覽器)。
  4、通過addEventListener添加的事件只能通過removeEventListener來移除;DOM 0級和DOM 2級事件可以在一個DOM上添加多個事件,按順序執(zhí)行
  5、DOM2級事件處理程序適用于:IE9、Firefox、Safari、Chrome和Opera

思考:那么如果我們想要兼容低版本的IE該怎么辦呢?請繼續(xù)往下閱讀

IE事件處理程序

(聲明:IE事件處理程序的代碼沒有進行測試)

IE實現(xiàn)了與DOM中類似的兩個方法:attachEvent()和detachEvent(),這兩個方法接受相同的兩個參數(shù):事件處理程序名稱與事件處理函數(shù)程序函數(shù)(因為IE8及更早版本只支持時間冒泡,所以沒有第三個參數(shù))。下面我們來看代碼:

var btn4 = document.getElementById("btn4"); btn4.attachEvent('onclick',function(){console.log("IE事件處理程序-onclick-01"); });

這里需要注意的是,第一個參數(shù)是onclick,而不是click。另外與DOM0級中的不同在于作用域,看下面的代碼:

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

其他需要注意的有:
1、attachEvent方法也可以為一個元素添加一個或多個事件處理程序,當添加多個相同的事件處理程序的時候,這些事件處理程序不是以添加它們的順序而執(zhí)行,而是以相反的順序被觸發(fā)。比如下面這個例子:

var btn4 = document.getElementById("btn4"); btn4.attachEvent('onclick',function(){console.log("hello"); }); btn4.attachEvent('onclick',function(){console.log("World"); });

這段代碼用DOM0級的方法得到的結(jié)果為World,用DOM2級的方法得到結(jié)果為先是hello然后是World,而在這里的結(jié)果為先是World然后是hello。

2、detachEvent()方法和DOM2級中移除的方法一樣,同樣也需要注意中間添加的匿名函數(shù)不能被移除,這里就不再舉例說明了。

從HTML事件處理程序到DOM0級事件處理程序,再到DOM2級處理程序,還有IE事件處理程序,我們在使用的時候為了讓用戶體驗最佳,我們該讓我們的代碼兼容各種瀏覽器,那么我們有什么好的方法讓我們的代碼兼容到各種瀏覽器中呢?

跨瀏覽器的事件處理程序

為了解決跨瀏覽器的問題,我們不得不集中的把前面幾種方法柔和在一起,然后就出現(xiàn)了跨瀏覽器的事件處理程序。(我的思路如下)

??? 1、先考慮添加事件的情況,在添加的時候,我們要知道給誰添加?添加的是什么事件?然后事件觸發(fā)的是什么函數(shù)?
?? ??? ?給誰添加?當然是我們的元素了,因為還不知道,這里我們先設置為element
?? ??? ?添加的是什么事件?click?onclick?onmouseover?我們也還是不知道,先設置為type吧
?? ??? ?添加什么函數(shù)?前面的例子中有用到過handler這里也先就用這個

function(element, type, handler) {……}

??? 2、我們要判斷我們的瀏覽器是否支持相關的操作,這里我們可以用if-else來判斷

if(element.addEventListener) {//DOM2級事件處理程序 } else if(element.attachEvent) {//IE事件處理程序 } else {//DOM0級事件處理程序 }

??? 3、針對DOM2級事件處理程序、IE事件處理程序和DOM0級事件處理程序它們有相似的地方,然后我們通過前面可以知道,它們對于事件的處理有點不和諧,我們該怎樣呢?很明顯,添加"on"比去掉"on"更簡單,所以比如點擊事件的type應該為click,然后在需要用onclick的地方,使用'on'+type,然后各自保留各自的特點?? ?
DOM2級事件處理程序:element.addEventListener(type, handler, false);
IE事件處理程序:element.attachEvent('on' + type, handler);
DOM0級事件處理程序:element['on' + type] = handler;

??? 4、到這里基本的添加情況以完成,接下來用同樣的方法來考慮移除事件的情況(步驟省略)

??? 5、然后分別給添加事件函數(shù)和移除事件函數(shù)進行命名addHandler和deleteHandler,并封裝起來,得到我們的最終效果:

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;}},deleteHandler: 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;}} }

事件對象

DOM中的事件對象

  前面我們已經(jīng)封裝好一個函數(shù)了,我們后面的操作直接引用前面的那個函數(shù)。說到事件對象,我們先不得不說事件對象的兩個重要屬性type和target
  其中type是獲取事件的類型,而target是獲取事件的目標。直接看代碼:

var btn = document.getElementById("btn"); eventUtil.addHandler(btn,'click',showMes); function showMes(event){alert(event.type);//結(jié)果是彈出click }

結(jié)果是彈出click,說明了該事件的類型是點擊事件

var btn = document.getElementById("btn"); eventUtil.addHandler(btn,'click',showMes); function showMes(event){alert(event.target);//結(jié)果是彈出[object HTMLInputElement] }

結(jié)果是彈出[object HTMLInputElement],說明該事件的目標是input元素

下面我們運行一段代碼,來看一個有趣的現(xiàn)象:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <div id="box"> ????<input type="button"?id="btn"?value="DOM中的事件對象"?/> ????<a href="www://baidu.com"?id="go">百度</a> </div> function showMes(event){ ????alert(event.target.nodeName); } function showBox(){ ????alert("這是放盒子的box") } var?btn = document.getElementById("btn"); var?box = document.getElementById("box"); eventUtil.addHandler(btn,'click',showMes); eventUtil.addHandler(box,'click',showBox);

?運行結(jié)果:鼠標點擊按鈕,分別彈出了“INPUT”和“這是放盒子的box”,我們只點擊了按鈕,為什么按鈕所在的div也會顯示呢?查資料知道這是因為事件冒泡機制導致的。

那么我們該如何阻止事件冒泡呢?

我們的事件對象給我們提供了一種方法:通過stopPropagation()方法來實現(xiàn),代碼示例如下:

function showMes(event){alert(event.target.nodeName);event.stopPropagation();//阻止事件冒泡 }function showBox(){alert("這是放盒子的box") }var btn = document.getElementById("btn"); var box = document.getElementById("box");eventUtil.addHandler(btn,'click',showMes); eventUtil.addHandler(box,'click',showBox);

光知道阻止事件冒泡行為還不行我們還需要知道的一種方法:阻止事件默認行為-->preventDefault()方法

比如我們知道的a標簽有一個默認行為就是跳轉(zhuǎn)到目標地址,如果我們想要阻止這種行為我們就可以使用該方法,代碼如下:

<a href="www://baidu.com" id="go">百度</a>var go = document.getElementById("go"); function showGo(event){event.stopPropagation();//阻止事件冒泡event.preventDefault();//阻止事件的默認行為 } eventUtil.addHandler(go,'click',showGo);

運行結(jié)果是,無論怎樣點擊,都跳轉(zhuǎn)不到百度頁面。
在a標簽里面阻止事件默認行為還有一種方法就是直接在a標簽里面添加,比如<a href="javascript:;">aa</a>

補充:在需要通過一個函數(shù)處理多個事件時,可以使用type屬性,比如:

var btn = document.getElementById("btn"); var handler = function(event){switch(event.type){case"click":alert("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;

IE中的事件對象

  【type屬性】用于獲取事件類型
  【srcElement屬性】用于獲取事件的目標(DOM中用的是target),所以,可以使用

event=event || window.event;(考慮IE8以前的版本) var ele=event.target event.srcElement;(考慮非IE與IE)

  【cancelBubble屬性】用于阻止事件冒泡,設為true表示阻止冒泡,false表示不阻止冒泡。
  【returnValue屬性】用于阻止事件的默認行為,設為false表示阻止。
  這里只介紹IE事件對象的常用屬性,關于它的具體例子就不做介紹了

跨瀏覽器的事件對象:

搞清楚前面的問題,下面的一段代碼看起來就簡單了。它直接將前面提到的所有方法和屬性一起封裝起來,并保存到一個單獨的js文件中,命名為event.js,其代碼如下:

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;},//獲取事件類型getType: function(event) {return event.type;},//獲取元素getElement: 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;}} }

?我們可以用如下代碼來測試點擊a事件

window.οnlοad=function(){var go=document.getElementById('go'),box=document.getElementById('box');eventUtil.addHandler(box,'click',function(){alert('我是整個父盒子');});eventUtil.addHandler(go,'click',function(e){//e=eventUtil.getEvent(e);e=e || window.event;alert(eventUtil.getElement(e).nodeName);eventUtil.preventDefault(e);eventUtil.stopPropagation(e);});}

?

事件類型

因為事件類型比較多,這里主要通過兩個具體的案例來展示,不做詳細介紹

案例一:用鼠標或鍵盤事件來控制抽獎。

效果截圖:

查看地址:http://sandbox.runjs.cn/show/0pibyaes

案例二:模仿扣扣登陸時的拖曳效果(主要學習其中如何實現(xiàn)拖曳效果的思維)

效果截圖:

查看地址:http://sandbox.runjs.cn/show/7mhb7pfw

更多參考資料:

  參考書籍:《Javascript高級程序設計(第三版)》

  參考博客:?https://my.oschina.net/u/1403185/blog/184960

    http://www.cnblogs.com/luozhihao/p/5934935.html

    http://www.cnblogs.com/xiaohuochai/p/5867195.html

轉(zhuǎn)載于:https://www.cnblogs.com/libin-1/p/5962125.html

總結(jié)

以上是生活随笔為你收集整理的彻底理解H5的DOM事件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。