摘要:推薦使用該方式進(jìn)行事件的注冊,可以對同一節(jié)點(diǎn)注冊多個事件處理函數(shù)。當(dāng)前冒泡流是被大多瀏覽器支持,因此大多賦為。阻斷事件的冒泡流或者事件捕獲流。資料推薦紅寶書阮一峰事件模型
一步,一步前進(jìn)の一步
事件是文檔或者瀏覽器窗口中發(fā)生的一些交互瞬間。JS注冊事件處理程序來預(yù)訂事件,當(dāng)事件發(fā)生的瞬間來執(zhí)行相應(yīng)的代碼,進(jìn)而實現(xiàn) JS 和 HTML(即文檔或者瀏覽器窗口) 的交互。
事件流事件流描述的是從頁面中接收事件的順序。
用手指戳一下屏幕上的同心圓的中心,先點(diǎn)到的是最外圍的大圓,還是最核心的小圓呢?這個就是事件流要處理的本質(zhì)問題。早起的 IE 和 Netscape 對此有不同的觀點(diǎn),IE認(rèn)為先點(diǎn)到的是最小的圓,然后在一層層的傳遞到最外面的大圓(事件冒泡),Netscape 正好相反,最先碰到的是最外圍的大圓,然后在一層層的追蹤到最精準(zhǔn)的小圓(事件捕獲)。
事件冒泡:事件開始由最具體的元素接收,然后逐級向上傳播到較為不具體的節(jié)點(diǎn)。
事件捕獲:事件是從不太具體的節(jié)點(diǎn)開始產(chǎn)生接收,而最具體的節(jié)點(diǎn)應(yīng)該是最后接收事件的。
事件流規(guī)范出來說,事件傳遞有三個階段: 捕獲階段、目標(biāo)階段、冒泡階段。
瀏覽器的事件處理大概就是注冊、監(jiān)聽。程序開始就對未來會發(fā)生的某些事情,做出預(yù)期,對預(yù)期做出正確的反應(yīng)。事件處理程序就是被注冊的正確反應(yīng),監(jiān)聽這個操作由瀏覽器自己完成。
瀏覽器提供了三種方法,為事件綁定監(jiān)聽函數(shù)。
需要注意的是:此處的事件處理程序是需要帶小括號的,大概的過程是當(dāng) div 接收到事件時,會將onclick后面的代碼原封不動的傳入JavaScript引擎執(zhí)行,不加小括號就不會觸發(fā)處理程序。
此方式會讓 js 的代碼和 html 代碼雜糅在一起,不易代碼的變更和維護(hù),因此不推薦使用。
Dom 0級事件注冊div.onclick = function (event) { console.log("觸發(fā)事件"); };以元素節(jié)點(diǎn)對象的事件屬性的方式進(jìn)行注冊,與第一種方式類似。
Dom 2級事件注冊
該事件只會在冒泡階段觸發(fā)。target.addEventListener(type, listener[, useCapture])
type事件名稱,大小寫敏感;listener處理函數(shù);useCapture是否在捕獲階段觸發(fā)。
推薦使用該方式進(jìn)行事件的注冊,可以對同一節(jié)點(diǎn)注冊多個事件處理函數(shù)。當(dāng)前冒泡流是被大多瀏覽器支持,因此useCapture大多賦為false。document.addEventListener("click", hello, false); document.addEventListener("click", hello2, false);IE 事件處理程序早期的 IE 瀏覽器只支持冒泡流,有自己的事件注冊和移除的方法:attachEvent()、detachEvent()
btn.attachEvent("onclick", function () { alert("ie browser"); });需要注意的是處理函數(shù)的 this 是指向 window 的,而不像前兩種事件處理函數(shù)的 this 會指向事件所在的 dom 節(jié)點(diǎn)對象。
跨瀏覽器事件處理程序紅寶書方案代碼如下:
var EventUtil = { addHandler: function(elm, type, handler) { if (elm.addEventListener) { elm.addEventListener(type, handler, false); } else if (elm.attachEvent) { elm.attachEvent("on" + type, handler); } else { elm["on" + type] = handler; } } };該方法是比較好的,但是處理函數(shù)執(zhí)行時的 this 指向還是有一點(diǎn)點(diǎn)問題,attachEvent方式還是指向 window 的,如果想更加完善,請參考 js 忍者秘籍上面的方案。
在處理事件時,我們需要考慮一些性能的問題,有必要限制事件處理函數(shù)的數(shù)量,適當(dāng)?shù)臅r候?qū)⒁延械氖录幚沓绦蛞瞥艋蛘卟捎檬录袡C(jī)制減少注冊的個數(shù)。下面我們簡單談?wù)勅绾我瞥录幚沓绦颉?/p>
var EventUtil = { removeHandler: function (elm, type, handler) { if (elm.removeEventListener) { elm.removeEventListener(type, handler, false); } else if (elm.detachEvent) { elm.detachEvent("on" + type, handle); } else { elm["on" + type] = handler; } } }事件的移除有個原則,怎么注冊的就要原封不動的 copy 參數(shù)調(diào)用移除。此處需要注意的是當(dāng)你的事件處理函數(shù)是匿名函數(shù)時,那將會永遠(yuǎn)也清理不掉了。
this 指向處理函數(shù)執(zhí)行時,this 指向現(xiàn)代的瀏覽器指向的是 事件所在dom 節(jié)點(diǎn),老 IE 指向window。
事件對象事件發(fā)生后,會產(chǎn)生一個事件對象,作為參數(shù)傳給監(jiān)聽函數(shù)。事件有若干的實例屬性和實例方法。只講下筆者認(rèn)為重要的currentTarget、target、preventDefault()、.stopPropagation()、stopImmediatePropagation()。
currentTarget事件處理函數(shù)注冊在什么節(jié)點(diǎn)上,那么 currentTarget 就永遠(yuǎn)的指向了該節(jié)點(diǎn)。
target,我們回顧一下事件流的概念,事件會經(jīng)歷捕獲階段、目標(biāo)階段、冒泡階段,可以感覺到事件的傳遞畫了個對稱的鉤,target 表示事件當(dāng)前所處的節(jié)點(diǎn)位置。
我們不僅可以讀取事件的狀態(tài),還可以人為的改變它的內(nèi)部狀態(tài)。preventDefault()阻止事件的默認(rèn)行為,如 a 標(biāo)簽被點(diǎn)擊時就會跳轉(zhuǎn)到新的 url,我們可以使用event.preventDefault()來阻止跳轉(zhuǎn)。
stopPropagation()阻斷事件的冒泡流或者事件捕獲流。但如果同一節(jié)點(diǎn)上注冊了多個事件處理程序,那么該節(jié)點(diǎn)上的事件處理程序會繼續(xù)處理,它只會阻斷事件向上或向下的傳播。
stopImmediatePropagation()更為狠毒,事件會停止在該事件處理程序上,同節(jié)點(diǎn)的其他事件處理程序也不會被觸發(fā)了。
事件代理由于事件會在冒泡階段向上傳播到父節(jié)點(diǎn),因此可以把子節(jié)點(diǎn)的監(jiān)聽函數(shù)定義在父節(jié)點(diǎn)上,由父節(jié)點(diǎn)的監(jiān)聽函數(shù)統(tǒng)一處理多個子元素的事件。這種方法叫做事件的代理(delegation)。
- test
- test
- test
- test
- test
...假設(shè)業(yè)務(wù)需要給 li 添加 click 監(jiān)聽事件,那么初學(xué)者可能會采用直接獲取 li 節(jié)點(diǎn)的方式進(jìn)行事件程序的綁定,那么有幾個 li,就需要注冊多少個事件處理程序??梢圆捎檬录頇C(jī)制實現(xiàn)性能優(yōu)化,代碼如下:
var ul = document.querySelector("ul"); ul.addEventListener("click", function (event) { if (event.target.tagName.toLowerCase() === "li") { // some code } });事件代理和事件委托是同一個東西,主要是利用事件冒泡和事件的實例屬性 target,目的是減少事件處理程序的數(shù)量,提高性能。
資料推薦紅寶書
阮一峰 事件模型
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/97039.html
摘要:異步任務(wù)必須指定回調(diào)函數(shù),當(dāng)異步任務(wù)從任務(wù)隊列回到執(zhí)行棧,回調(diào)函數(shù)就會執(zhí)行。事件循環(huán)主線程從任務(wù)隊列中讀取事件,這個過程是循環(huán)不斷的,所以整個的這種運(yùn)行機(jī)制又稱為。事件循環(huán)事件循環(huán)是指主線程重復(fù)從消息隊列中取消息執(zhí)行的過程。 參考鏈接:這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制https://zhuanlan.zhihu.com/p/...從瀏覽器多進(jìn)程到JS單線程,JS運(yùn)行機(jī)制...
摘要:有兩種事件處理程序的方式。第一種第二種事件當(dāng)調(diào)整瀏覽器的窗口到一個新的寬度或高度時,就會觸發(fā)事件。事件在元素獲得焦點(diǎn)時觸發(fā)。這個事件冒泡某些瀏覽器不支持。事件在鼠標(biāo)光標(biāo)從元素外部首次移動到元素范圍內(nèi)時觸發(fā)。事件這個事件跟蹤鼠標(biāo)滾輪。 JavaScript簡單入門可以看看我丑丑的Github博客JavaScript簡單入門 本文主要簡單介紹以下幾類事件: UI事件 焦點(diǎn)事件 鼠標(biāo)與滾輪...
摘要:響應(yīng)某個事件的函數(shù)就叫事件處理程序或事件偵聽器。為事件指定事件處理程序的方法主要有種。事件處理程序事件直接加在元素上。事件委托利用冒泡的原理,把事件加到父元素或祖先元素上,觸發(fā)執(zhí)行效果,解決事件處理程序過多問題。事件委托優(yōu)點(diǎn)提高性能。 JavaScript簡單入門可以看看我丑丑的Github博客JavaScript簡單入門 事件 JavaScript與HTML之間的交互是通過事件實現(xiàn)的...
摘要:提示如需移除事件處理程序,請使用方法。說明和綁定的點(diǎn)擊事件被的事件覆蓋。分析不同的綁定方式執(zhí)行順序?qū)傩栽厥录录?。元素綁定事件刪除按鈕。屬性綁定事件動態(tài)綁定事件方法的方法的屬性綁定。 一、動態(tài)監(jiān)聽加載對象 當(dāng)使用js或jQuery動態(tài)創(chuàng)建元素(例如append,appendChildren),再用on(事件, function(){...})或addEventListener監(jiān)聽事件...
摘要:鼠標(biāo)滾輪事件當(dāng)在被綁定的對象上如某個或者發(fā)生鼠標(biāo)滾輪滾動時觸發(fā)。 鼠標(biāo)滾輪事件 當(dāng)在被綁定的對象上(如:某個div或者doucument)發(fā)生鼠標(biāo)滾輪滾動時觸發(fā)。 在不同的瀏覽器中有不同的表現(xiàn)形式: 一、ie/chrome下的事件 : onmousewheel 事件綁定方式:on 或者 addEventListener[attachEvent] 獲取滾輪事件具體信息:ev...
摘要:要想注冊過的事件能夠被解除,必須將回調(diào)函數(shù)保存起來,否則無法解除。當(dāng)用阻止瀏覽器的默認(rèn)行為時,會做下面這件事停止回調(diào)函數(shù)執(zhí)行并立即返回。 showImg(https://segmentfault.com/img/bVboOcb?w=750&h=422); 前言 這是前端面試題系列的第 7 篇,你可能錯過了前面的篇章,可以在這里找到: 理解函數(shù)的柯里化 ES6 中箭頭函數(shù)的用法 thi...
閱讀 2355·2019-08-30 15:44
閱讀 1279·2019-08-30 13:01
閱讀 3319·2019-08-30 11:22
閱讀 3106·2019-08-29 15:23
閱讀 1626·2019-08-29 12:22
閱讀 3386·2019-08-26 13:58
閱讀 3455·2019-08-26 12:17
閱讀 3491·2019-08-26 12:16