談?wù)勎覍?duì)JavaScript DOM事件的理解
什么是事件?
事件(Event)是JavaScript應(yīng)用跳動(dòng)的心臟 ,也是把所有東西粘在一起的膠水。當(dāng)我們與瀏覽器中 Web 頁(yè)面進(jìn)行某些類型的交互時(shí),事件就發(fā)生了。事件可能是用戶在某些內(nèi)容上的點(diǎn)擊、鼠標(biāo)經(jīng)過(guò)某個(gè)特定元素或按下鍵盤上的某些按鍵。事件還可能是 Web 瀏覽器中發(fā)生的事情,比如說(shuō)某個(gè) Web 頁(yè)面加載完成,或者是用戶滾動(dòng)窗口或改變窗口大小。
通過(guò)使用 JavaScript ,你可以監(jiān)聽(tīng)特定事件的發(fā)生,并規(guī)定讓某些事件發(fā)生以對(duì)這些事件做出響應(yīng)。
DOM與事件是JavaScript最核心的組成部分之一,他們賦予了頁(yè)面無(wú)限的想象空間,你根本無(wú)法離開他們,否則js將寸步難行。在我們平時(shí)的開發(fā)過(guò)程中,jQuery的出現(xiàn)使得我們得心應(yīng)手,然而你必須知道,jQuery之所以把事情簡(jiǎn)單化,是得益于JavaScript本身提供的強(qiáng)大的API,你應(yīng)該去熟悉它們。
首先,此文不討論繁瑣細(xì)節(jié),但是考慮到讀者的心靈感受,本著以積極向上的心態(tài),在此還是會(huì)列舉示例說(shuō)明。
標(biāo)題為理解DOM事件,那么在此拿一個(gè)簡(jiǎn)單的點(diǎn)擊事件為例,希望大家看到這個(gè)例子后能觸類旁通。
最初我們給頁(yè)面實(shí)現(xiàn)點(diǎn)擊,就像下面這樣的簡(jiǎn)單操作。
先定義一個(gè)塊如<div id="weiyuzhou">微宇宙</div>,之后在<script type="text/javascript"></script>內(nèi)部實(shí)現(xiàn)id為weiyuzhou的點(diǎn)擊事件,如下代碼所示:
var wyz = document.getElementById('weiyuzhou'); wyz.onclick = function () { confirm(arguments.length) }
確保上面這些步驟都沒(méi)問(wèn)題的話,我們才可以繼續(xù)的往下走,然后我們?cè)贗E瀏覽器(低版本)看到彈出0,確切的說(shuō),IE8以下(包含IE8)的彈出0,反之彈出1。接著我在firefox瀏覽器看到彈出1。也就是說(shuō)在IE8以下版本事件的觸發(fā)不存在于函數(shù)的作用域內(nèi)部,是不是說(shuō)IE8以下的事件觸發(fā)發(fā)生在全局作用域中,此處留個(gè)懸念,但是,可以肯定的是IE8以下事件的方法并沒(méi)有這個(gè)Event參數(shù),也就是說(shuō)arguments的長(zhǎng)度為0,如下視圖5-02所示:
5-02
于是,我們看firefox瀏覽器窗口彈出1,說(shuō)明事件存在于函數(shù)內(nèi)部,再次證明方法的內(nèi)部數(shù)組arguments長(zhǎng)度為1,并且是可枚舉的變量,也可以說(shuō)可寫,如下視圖5-03所示。
5-03
如果,你還是不明白其中的原理,你不防去看一下《web前端開發(fā)修煉之道》書上第169頁(yè),然后再回過(guò)頭來(lái)看此處文章摘要,可能會(huì)讓你更加深層次的了解書中的內(nèi)容。
接下來(lái),我們?cè)撛趺崔k呢,我們肯定不能讓IE和firefox返回的事件輸出不相同,那么如何讓IE和firefox下彈出的內(nèi)容都一樣。
銜接上一段內(nèi)容,下面給點(diǎn)擊函數(shù)的內(nèi)部設(shè)置一個(gè)參數(shù),參數(shù)名為e,然后在IE和firefox瀏覽器下面同時(shí)觸發(fā)點(diǎn)擊事件,我們看到firefox下面顯示e為鼠標(biāo)事件[object MouseEvent],IE8下報(bào)錯(cuò),彈出錯(cuò)誤信息未定義undefined。此時(shí)你要問(wèn)我錯(cuò)在哪里,咱們回到剛剛的那句話‘此處留個(gè)懸念'進(jìn)行分析,IE8以下的瀏覽器的事件是不是發(fā)生在全局作用域中,從視圖5-02所示看到有一個(gè)global全局對(duì)象,我們可以對(duì)global展開搜索,global的繼承的方法有一個(gè)event事件,找到了IE8的專有事件方法window繼承event,于是我們對(duì)這個(gè)參數(shù)e設(shè)置為window.event進(jìn)行一個(gè)調(diào)試,目前我們?cè)贗E8下面看到返回了一個(gè)事件[object event],如圖5-04所示。
5-04
想必你一定發(fā)現(xiàn)了IE8和firefox瀏覽器下對(duì)話框的事件返回值各不不同,IE8的對(duì)話框[object MouseEvent],firefox的對(duì)話框[object event],那我們?cè)趺醋孖E8和firefox下的返回值都相同呢?
看到這里,你的心里是不是有點(diǎn)小沮喪,挖坑挖了這么久了,怎么還沒(méi)有看到水流出來(lái),別急,正題才剛剛開始,咱們不閑聊,繼續(xù)圍繞正題展開分析,通過(guò)剛剛的返回值,我們繼續(xù)使用斷點(diǎn)的方法尋找能夠?qū)崿F(xiàn)IE和firefox的返回值的共同點(diǎn)。
經(jīng)由以上分析,我們查找發(fā)現(xiàn)firefox下的event有我們需要的方法名可以被調(diào)用,當(dāng)然,我們查找發(fā)現(xiàn)IE8下面的srcElement也有我們所需的方法名可以被調(diào)用,于是乎,呵呵!看到這里你的內(nèi)心是不是有點(diǎn)小激動(dòng),一步步排除,最后發(fā)現(xiàn)也沒(méi)有什么難的?;氐秸},現(xiàn)在我們聲明一個(gè)變量var e_child = e.srcElement || e.target; 然后我們?cè)贗E8和firefox瀏覽器上看到對(duì)話框信息都為[object HTMLDivElement],如圖5-05所示。
5-05
現(xiàn)在我們解決了不同瀏覽器的返回值不同的問(wèn)題,也就是說(shuō)解決了兼容的問(wèn)題,這只是冰上一角。
下面我們要解決實(shí)現(xiàn)窗口的容器觸發(fā)事件,主要是基于上面的結(jié)構(gòu)進(jìn)行的一次分析。
當(dāng)你有了上面基礎(chǔ)的話,下面的內(nèi)容相對(duì)于上面而言比較簡(jiǎn)單一點(diǎn)。
還是以上一個(gè)頁(yè)面的塊為例,現(xiàn)在我繼續(xù)往塊<div id="weiyuzhou">微宇宙</div>增加一個(gè)子容器,這個(gè)子容器為行內(nèi)元素<span id='coz'>koringz</span>,取id名為coz,然后給這個(gè)元素也加一個(gè)點(diǎn)擊事件代碼同上函數(shù),為了能區(qū)別開文本內(nèi)容之間的差異。
當(dāng)我分別在IE8和firefox下點(diǎn)擊容器的內(nèi)容,出現(xiàn)了怪異的情況,在firefox瀏覽器的窗口上點(diǎn)擊時(shí),點(diǎn)擊中文文本內(nèi)容彈出來(lái)對(duì)話框‘微宇宙',我再點(diǎn)擊koringz時(shí),發(fā)現(xiàn)彈出了二次對(duì)話框,彈出內(nèi)容都為'koringz',那是因?yàn)槲尹c(diǎn)擊子容器的時(shí)候觸發(fā)了上一層的點(diǎn)擊行為,如何解決點(diǎn)擊koringz彈出二次對(duì)話框的問(wèn)題,了解一點(diǎn)js的程序員都知道這是冒泡事件。
那么在firefox能夠清除冒泡事件的是event下的stopPropagation,于是我們給第二次點(diǎn)擊事件函數(shù)代碼塊之后面加一行代碼e.stopPropagation();之后再點(diǎn)擊koringz發(fā)現(xiàn)彈出一次'koringz'。如圖5-06所示
5-06
接下來(lái)在IE8下面測(cè)試一下,發(fā)現(xiàn)在IE8瀏覽器點(diǎn)擊也彈出二次,解決IE8的停止冒泡事件為cacelBubble,且我們只需要給cacelBubble設(shè)置為true即可。
因?yàn)镮E8下global包含的event屬性cacelBubble不是一個(gè)方法,而是一個(gè)輸出布爾值的對(duì)象,所以這個(gè)和firefox有所不同,只是firefox把此事件封裝成方法而已。好了,現(xiàn)在我們給第二次點(diǎn)擊的事件代碼塊之后再加一行代碼e.cancelBubble = true;然后在IE8瀏覽器下測(cè)試,之后再點(diǎn)擊koringz發(fā)現(xiàn)也彈出一次。如圖5-07所示
5-07
注意上面的停止冒泡的事件的代碼可以根據(jù)瀏覽器的不同分開來(lái)寫,如何分開寫,我們查看IE8瀏覽器下面的document發(fā)現(xiàn)存在對(duì)象all,而在firefox卻沒(méi)有沒(méi)有這個(gè)all屬性,這也就是說(shuō)document.all是IE8版本下面獨(dú)有的一個(gè)屬性。通過(guò)它我們可以區(qū)分瀏覽器的冒泡事件。
到目前為止,我們解決了窗口的冒泡事件,接下來(lái),我們要解決一個(gè)事件因被多人定義而覆蓋原函數(shù)的問(wèn)題。也可能是說(shuō)某公司之前的工作人員添加了此事件,后來(lái)新員工接手項(xiàng)目后添加修改此事件而覆蓋了原事件的執(zhí)行所產(chǎn)生的問(wèn)題。也就是說(shuō)給當(dāng)前id多次添加此類事件都不會(huì)覆蓋此事件的原函數(shù)執(zhí)行。
在firefox下的window包含有addEventListener(type, listener, useCapture)的方法,隨后我們?cè)?lt;script type="text/javascript"></script>內(nèi)部定義此監(jiān)聽(tīng)事件domElement.addEventListener('click',function(e){confirm(e+'e')},false);,接著在firefox瀏覽器點(diǎn)擊內(nèi)容彈出二次,最后一次彈出為[object MouseEvent]e,后面多了一個(gè)e,這是我有意加上用以區(qū)別的。如圖5-08所示。
5-08
接下來(lái)在IE8下測(cè)試發(fā)現(xiàn)addEventListener錯(cuò)誤,但是看到window下有此類方法(嘗試了一下,原來(lái)此類方法在IE9以上版本是可以被支持),IE8同時(shí)還有一個(gè)attachEvent(event, pdisp),那么我們?cè)O(shè)置監(jiān)聽(tīng)事件wyz.attachEvent('onclick',function(e){confirm(e + 'e')}),注:event為'onclick',緊接著在IE8下點(diǎn)擊發(fā)現(xiàn)可彈出二次,最后一次eIE。此時(shí)on('click',pdisp)和attachEvent(event,pdisp)可以共同使用。
綜上所述,我們解決了DOM事件的兼容性,DOM事件的冒泡,以及DOM事件的重用。
- Javascript DOM事件操作小結(jié)(監(jiān)聽(tīng)鼠標(biāo)點(diǎn)擊、釋放,懸停、離開等)
- JavaScript DOM事件(筆記)
- JavaScript call apply使用 JavaScript對(duì)象的方法綁定到DOM事件后this指向問(wèn)題
- JS對(duì)象與JSON互轉(zhuǎn)換、New Function()、 forEach()、DOM事件流等js開發(fā)基礎(chǔ)小結(jié)
- 關(guān)于javascript DOM事件模型的兩件事
- javascript循環(huán)變量注冊(cè)dom事件 之強(qiáng)大的閉包
- 深入理解JS DOM事件機(jī)制
- 理解javascript中DOM事件
- js中DOM事件綁定分析
- js實(shí)現(xiàn)QQ面板拖拽效果(慕課網(wǎng)DOM事件探秘)(全)
- JavaScript將DOM事件處理程序封裝為event.js 出現(xiàn)的低級(jí)錯(cuò)誤問(wèn)題
- js DOM的事件常見(jiàn)操作實(shí)例詳解
相關(guān)文章
正則中的回溯定義與用法分析【JS與java實(shí)現(xiàn)】
這篇文章主要介紹了正則中的回溯定義與用法,結(jié)合實(shí)例形式分析了回溯的概念、功能并提供了JS與java實(shí)現(xiàn)方法,需要的朋友可以參考下2016-12-12JavaScript動(dòng)態(tài)操作表格實(shí)例(添加,刪除行,列及單元格)
這篇文章主要是對(duì)JavaScript動(dòng)態(tài)操作表格實(shí)例(添加,刪除行,列及單元格)進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-11-11在JavaScript中call()與apply()區(qū)別
這篇文章主要介紹了在JavaScript中call()與apply()區(qū)別 的相關(guān)資料,需要的朋友可以參考下2016-01-01js中document.referrer實(shí)現(xiàn)移動(dòng)端返回上一頁(yè)
本文主要介紹了document.referrer實(shí)現(xiàn)移動(dòng)端返回上一頁(yè)的方法,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02前端axios下載excel文件(二進(jìn)制)的處理方法
新接了項(xiàng)目,遇到這樣的需求,通過(guò)后端接口下載excel文件,后端沒(méi)有文件地址,返回二進(jìn)制流文件。接下來(lái)通過(guò)實(shí)例代碼給大家分享前端axios下載excel文件(二進(jìn)制)的處理方法,一起看看吧2018-07-07js實(shí)現(xiàn)旋轉(zhuǎn)大風(fēng)車
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)旋轉(zhuǎn)大風(fēng)車,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02微信小程序?qū)崿F(xiàn)短信登錄的實(shí)戰(zhàn)
項(xiàng)目要求增加短信登錄及人臉識(shí)別登錄功能,本文就來(lái)實(shí)現(xiàn)一下 短信登錄功能,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10javascript實(shí)現(xiàn)生成并下載txt文件方式
這篇文章主要介紹了javascript實(shí)現(xiàn)生成并下載txt文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09