成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

讀書筆記(05) - 事件 - JavaScript高級程序設(shè)計

tinylcy / 2711人閱讀

摘要:而事件分為個級別級事件處理程序,級事件處理程序和級事件處理程序。級中沒有規(guī)范事件的相關(guān)內(nèi)容,所以沒有級事件處理。

HTML依托于JavaScript來實現(xiàn)用戶與WEB網(wǎng)頁之間的動態(tài)交互,接收用戶操作并做出相應(yīng)的反饋,而事件在此間則充當(dāng)橋梁的重要角色。

日常開發(fā)中,經(jīng)常會為某個元素綁定一個事件,編寫相應(yīng)的業(yè)務(wù)邏輯,在元素被點擊時執(zhí)行,并反饋到用戶操作界面。

這個過程中,事件就像一個偵聽器,當(dāng)點擊動作發(fā)生時,才會執(zhí)行對應(yīng)的程序。這種模式可稱之為觀察員模式。

接下來就講講DOM事件相關(guān)知識。

何為事件
事件就是用戶或瀏覽器自身執(zhí)行的某種動作

常用的DOM事件有click/mouseover/mouseout/keyup/keydown等。

事件流
事件流描述的是從頁面中接收事件的順序

HTML描述的是一個DOM文檔結(jié)構(gòu),而事件流所描述的是DOM文檔節(jié)點接收事件順序。

而事件流有兩種事件模式,捕獲/冒泡,兩者所描述的事件傳遞順序?qū)α⑾喾础?/p> 事件模式:捕獲與冒泡

冒泡
事件冒泡:事件開始時由最具體的元素(文檔中嵌套層次最深的那個節(jié)點)接收,然后逐級向上傳播到較為不具體的節(jié)點(文檔)

規(guī)范要求事件冒泡到document對象,而瀏覽器則會將事件一直冒泡到window對象。

所有瀏覽器都支持事件冒泡(包括IE9以下)。

捕獲
事件捕獲:(與事件冒泡相反)事件捕獲的思想是不太具體的節(jié)點應(yīng)該更早接收到事件,而最具體的節(jié)點應(yīng)該最后接收到事件

與冒泡一樣,雖然規(guī)定事件應(yīng)該從document對象開始傳播,但瀏覽器普遍都是從window對象開始捕獲。

IE9以下不支持事件捕獲

DOM 事件流

"DOM2級事件"規(guī)定事件流包括三個階段,順序進(jìn)行

事件捕獲階段

處于目標(biāo)階段

事件冒泡階段

TIPS: 實際的目標(biāo)元素在捕獲階段不會接收到事件,在處于目標(biāo)階段時接收事件發(fā)生處理,并被看成是冒泡階段的一部分。

盡管"DOM2級事件"規(guī)范明確要求捕獲階段不會涉及事件目標(biāo),但瀏覽器會在捕獲階段觸發(fā)事件對象上的事件。

?事件處理程序
響應(yīng)某個事件的函數(shù)方法,我們稱之為事件處理程序(或事件偵聽器)
window.onclick = function() {
    //...
}
// 這里的function(){}就是事件處理程序
HTML事件處理程序

HTML中元素支持的事件,可以使用一個同名的HTML特性來指定,而這個特性的值就是js能執(zhí)行的代碼或表達(dá)式。寫法上可以看出類似HTML中id/type/class等屬性的寫法,都是on+"..."

缺點:HTML是結(jié)構(gòu)層(顯示層),而JavaScript是行為層(業(yè)務(wù)層)。在顯示層上去編寫業(yè)務(wù)邏輯代碼處理,會使得HTML與JavaScript代碼耦合過于緊密,不好維護(hù)。

DOM級別一共可以分為四個級別:DOM0級、DOM1級、DOM2級和DOM3級。

DOM事件分為3個級別:DOM 0級事件處理程序,DOM 2級事件處理程序和DOM 3級事件處理程序。DOM 1級中沒有規(guī)范事件的相關(guān)內(nèi)容,所以沒有DOM 1級事件處理。

DOM0 級事件處理程序

每個元素(HTML元素)都有自己的事件處理程序?qū)傩?,屬性名通常以on開頭,例如onclick/onmouseover。為這個屬性的值設(shè)置一個函數(shù),就可以指定事件處理程序。而將其屬性值賦值為null,則完成解綁。(同個元素?zé)o法綁定多個同名事件)

var myBtn = document.getElementById("myBtn");

// 為myBtn綁定事件處理程序, 只能綁定一個
myBtn.onclick = function() {
    alert("Hello world!");
}

// 解綁
myBtn.onclick = null;
DOM2 級事件處理程序

"DOM2級事件"定義了兩個方法,addEventListener()/removeEventListener(),用于為元素綁定和解綁事件。

可綁定多個事件,區(qū)別于DOM0級/HTML僅能綁定一個)。

el.addEventListener(eventName, callBack, useCapture)

eventName: 事件名稱

callBack: 回調(diào)函數(shù),當(dāng)事件觸發(fā)時,函數(shù)會傳入一個參數(shù)event,為當(dāng)前的事件對象

useCapture: 默認(rèn)是false,代表事件句柄在冒泡階段執(zhí)行, true則代表在捕獲階段執(zhí)行

var myBtn = document.getElementById("myBtn");

var handleClick = function() {
    alert("Hello world!");
}
// 綁定事件處理程序
myBtn.addEventListener("click", handleClick, false);

// 解綁
myBtn.removeEventListener("click", handleClick);

TIPS:DOM2級事件處理程序,解綁時function必須與傳入addEventListener相同

// 綁定
myBtn.addEventListener("click", function() {
    // 匿名函數(shù)
});

// 解綁
myBtn.removeEventListener("click",function() {
    // 匿名函數(shù)
});

// add/remove 分別綁定了兩個匿名函數(shù)(函數(shù)為引用類型),所以兩個函數(shù)并不相同,所以無法成功解綁

TIPS:綁定多個事件處理程序時,執(zhí)行順序按綁定順序執(zhí)行

myBtn.addEventListener("click", function() {
    // step1...
})
myBtn.addEventListener("click", function() {
    // step2...
})

// 執(zhí)行順序:step1 -> step2

瀏覽器支持情況:IE9以下不支持DOM2級事件處理程序

IE 事件處理程序

IE9以下不支持DOM2級事件,但I(xiàn)E提供了與DOM2級事件類似的兩個方法,attachEvent()/detachEvent,IE9以下不支持事件捕獲,所以attachEvent僅支持冒泡階段觸發(fā),只接收兩個參數(shù)(eventName, function)。

// 綁定
myBtn.attachEvent("onclick", handleClick);

// 解綁
myBtn.detachEvent("onclick", handleClick);

TIPS:

解綁時function必須與傳入attachEvent相同,這點與DOM2級事件相同

與DOM0級的區(qū)別,DOM0級事件處理在元素的作用域運行,而attachEvent事件處理在全局,this指向window

綁定多個事件處理程序時,執(zhí)行順序按綁定順序逆反執(zhí)行(與DOM2級相反)

myBtn.attachEvent("click", function() {
 // step1...
})
myBtn.attachEvent("click", function() {
 // step2...
})
// 執(zhí)行順序:step2 -> step1
Event 事件對象 常見應(yīng)用
event.preventDefault()

阻止默認(rèn)事件

event.stopPropagation()

阻止事件流發(fā)生傳遞(冒泡/捕獲)

event.stopImmediatePropagation()

阻止剩余事件處理函數(shù)的執(zhí)行,并阻止當(dāng)前事件在事件流上傳遞

event.currentTarget

當(dāng)前綁定事件的元素

event.target

當(dāng)前觸發(fā)事件的元素

event.stopPropagation()與.stopImmediatePropagation()的區(qū)別

同個元素綁定多個同名事件時,stopImmediatePropagation不僅阻止了冒泡,而且會阻止后續(xù)事件的執(zhí)行,可以理解為加強(qiáng)版的stopPropagation

myBtn.addEventListener("click", function(event) {
    // step1;
    event.stopImmediatePropagation();
})

myBtn.addEventListener("click", function(event) {
    // step2;
    // 我被stopImmediatePropagation阻止掉了?。?!
})
currantTarget與target的區(qū)別

事件處理程序內(nèi)部,this等于currentTarget(當(dāng)前綁定事件的元素),而target(當(dāng)前觸發(fā)事件的元素)

// currentTarget == target
myBtn.addEventListener("click", function(event) {
    event.target == event.currentTarget; // true -> myBtn
})

// currentTarget != target 捕獲/冒泡
document.body.addEventListener("click", function(event){
    event.target == event.currentTarget; // false
    // event.target -> myBtn
    // event.currentTarget -> body
})
內(nèi)存與性能

WEB網(wǎng)頁是運行在瀏覽器客戶端的,而計算機(jī)分配給瀏覽器的內(nèi)存及CPU占用是有限制的。雖說瀏覽器引擎不斷地發(fā)展優(yōu)化,但是內(nèi)存占用多了, 性能不免會損耗。

內(nèi)存

為元素指定事件綁定程序,事實上是賦值了一個函數(shù)方法,而函數(shù)在javaScript中是一種引用類型的數(shù)據(jù)格式,既然是數(shù)據(jù)那就需要用到內(nèi)存儲存。函數(shù)創(chuàng)建多了,消耗掉內(nèi)存。

性能

為元素指定事件綁定程序,首先需要對DOM進(jìn)行查詢,找出要綁定事件的元素。而這也會造成DOM元素的訪問次數(shù)增加。DOM的操作一直是網(wǎng)頁性能的一個優(yōu)化點。

了解完事件綁定帶來內(nèi)存跟性能的原理,我們來看一個例子,例如我們有一個ul>li的列表,要監(jiān)聽每一個li的點擊事件,并觸發(fā)事件處理程序。

多帶帶綁定的話,10個li就要對DOM元素查詢10次,創(chuàng)建的匿名函數(shù)就有10個(當(dāng)然可以共同創(chuàng)建同個函數(shù)引用),如果還有20個,30個,100個,那么這種為每個li元素多帶帶綁定事件的方法,絕對不是最優(yōu)解。

這就引出下面的優(yōu)化方案:"事件委托"。

事件委托(事件代理)

對"事件處理程序綁定過多"的問題,最好的解決方案就是"事件委托"。它的原理是利用了事件流的"冒泡"機(jī)制,事件目標(biāo)元素會把事件向上層傳遞,直到document(瀏覽器會傳到window),所以父級節(jié)點是可以接收子節(jié)點的事件傳遞。

以剛剛ul>li的例子,li有很多個, 但它們有一個共同的父節(jié)點ul。li的點擊事件會冒泡到ul,因此我們可以在ul上綁定一個事件處理程序,處理所有li的點擊事件,然后通過event.target可以確定觸發(fā)事件的元素。

var ulParent = document.getElementById("parent");
ulParent.addEventListener("click", function(event) {
    var taget = event.target; 
})

通過"事件委托"減少了DOM元素的查詢,以及多個函數(shù)的內(nèi)存占用,而且還有一個好處,當(dāng)我們的li是動態(tài)的,增加和移除時,都無需再做綁定和解綁事件操作,因為它都會冒泡到父級節(jié)點。

移除多余的事件綁定

文檔中移除了綁定了事件的DOM元素,如innerHTML/removeChild()/replaceChild()等可以對DOM進(jìn)行替換,而移除的DOM元素原先所綁定的事件處理程序,并不能有效被瀏覽器垃圾回收,所以占用一直存在。

所以建議在移除某個DOM元素時,如果其綁定了事件處理程序,需手動解除綁定,釋放內(nèi)存。

自定義事件

除了為元素綁定支持的事件以外,我們還可以通過Event/CustomEvent來創(chuàng)建開發(fā)者自定義事件。

兩者不同的是CustomEvent可傳遞一個Object對象來傳輸數(shù)據(jù)。

// Event
var eve = new Event("custome");

// CustomeEvent 可傳參數(shù)
var eve = new CustomeEvent("custome", {
    detail: {
        name: "KenTsang",
        age: 28
    }
});

// 為DOM元素添加事件監(jiān)聽
ele.addEventListener("custome", function(event) {
    console.log(event.detail);
})

// 觸發(fā)ele綁定的自定義事件
ele.dispatch(eve);

事件這塊還剩下一部分知識點,后續(xù)文章會再就模擬事件這塊知識點進(jìn)行拆分詳解。

天冷了,更文不易,望大家多多點贊。

《JavaScript高級程序設(shè)計》

作者:以樂之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。轉(zhuǎn)載請指明出處。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99880.html

相關(guān)文章

  • 001-讀書筆記-JavaScript高級程序設(shè)計 JavaScript簡介

    摘要:由于計算機(jī)的國際化,組織的標(biāo)準(zhǔn)牽涉到很多其他國家,因此組織決定改名表明其國際性。規(guī)范由萬維網(wǎng)聯(lián)盟制定。級標(biāo)準(zhǔn)級標(biāo)準(zhǔn)是不存在的,級一般指的是最初支持的。 這篇筆記的內(nèi)容對應(yīng)的是《JavaScript高級程序設(shè)計(第三版)》中的第一章。 1.ECMA 和 ECMA-262 ECMA 是歐洲計算機(jī)制造商協(xié)會的縮寫,全程是 European Computer Manufacturers Ass...

    masturbator 評論0 收藏0
  • 讀書筆記(02) - 可維護(hù)性 - JavaScript高級程序設(shè)計

    摘要:解耦優(yōu)勢代碼復(fù)用,單元測試。常用比較誤區(qū)可同時判斷,可用來判斷對象屬性是否存在。使用作判斷無法進(jìn)行充分的類型檢查。文件中應(yīng)用常量參考文檔高級程序設(shè)計作者以樂之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVburXw?w=500&h=400); 編寫可維護(hù)性代碼 可維護(hù)的代碼遵循原則: 可理解性 (方便他人理解) 直觀...

    k00baa 評論0 收藏0
  • 讀書筆記(04) - 錯誤監(jiān)控 - JavaScript高級程序設(shè)計

    摘要:項目中我們可通過設(shè)置采集率,或?qū)σ?guī)定時間內(nèi)數(shù)據(jù)匯總再上報,減少請求數(shù)量,從而緩解服務(wù)端壓力。借鑒別人的一個例子只采集上報錯誤參考文檔高級程序設(shè)計如何優(yōu)雅處理前端異常作者以樂之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVbnuud?w=640&h=640); 錯誤類型 即時運行錯誤 (代碼錯誤) 資源加載錯誤 常見...

    Null 評論0 收藏0
  • 讀書筆記(03) - 性能 - JavaScript高級程序設(shè)計

    摘要:作用域鏈查找作用域鏈的查找是逐層向上查找。而全局變量和閉包則會與之相反,繼續(xù)保存,所以使用用后需手動標(biāo)記清除,以免造成內(nèi)存泄漏。獲取元素的屬性獲取元素的屬性等參考文檔高級程序設(shè)計作者以樂之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVburXV?w=500&h=399); 作用域鏈查找 作用域鏈的查找是逐層向上查找。查...

    warnerwu 評論0 收藏0
  • 002-讀書筆記-JavaScript高級程序設(shè)計 在HTML中使用JavaScript

    摘要:文件內(nèi)部使用使用到的代碼引入外部文件外部代碼的地址標(biāo)簽的位置一般情況下,標(biāo)簽的位置放在標(biāo)簽中引入代碼頁面結(jié)構(gòu)對于需要引入很多的中間,如果把放在頭部,無疑會導(dǎo)致瀏覽器呈現(xiàn)頁面出現(xiàn)延遲,就是導(dǎo)致頁面出現(xiàn)空白。頁面結(jié)構(gòu)引入代碼 這篇筆記的內(nèi)容對應(yīng)的是《JavaScript高級程序設(shè)計(第三版)》中的第二章。 1.使用方式 在HTML中使用 JavaScript 的方式有兩種,第一種就是直接內(nèi)...

    banana_pi 評論0 收藏0

發(fā)表評論

0條評論

tinylcy

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<