成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

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

tinylcy / 2754人閱讀

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

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

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

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

接下來(lái)就講講DOM事件相關(guān)知識(shí)。

何為事件
事件就是用戶或?yàn)g覽器自身執(zhí)行的某種動(dòng)作

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

事件流
事件流描述的是從頁(yè)面中接收事件的順序

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

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

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

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

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

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

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

IE9以下不支持事件捕獲

DOM 事件流

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

事件捕獲階段

處于目標(biāo)階段

事件冒泡階段

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

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

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

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

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

DOM級(jí)別一共可以分為四個(gè)級(jí)別:DOM0級(jí)、DOM1級(jí)、DOM2級(jí)和DOM3級(jí)。

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

DOM0 級(jí)事件處理程序

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

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

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

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

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

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

el.addEventListener(eventName, callBack, useCapture)

eventName: 事件名稱

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

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級(jí)事件處理程序,解綁時(shí)function必須與傳入addEventListener相同

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

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

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

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

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

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

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

IE 事件處理程序

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

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

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

TIPS:

解綁時(shí)function必須與傳入attachEvent相同,這點(diǎn)與DOM2級(jí)事件相同

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

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

myBtn.attachEvent("click", function() {
 // step1...
})
myBtn.attachEvent("click", function() {
 // step2...
})
// 執(zhí)行順序:step2 -> step1
Event 事件對(duì)象 常見(jiàn)應(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ū)別

同個(gè)元素綁定多個(gè)同名事件時(shí),stopImmediatePropagation不僅阻止了冒泡,而且會(huì)阻止后續(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)頁(yè)是運(yùn)行在瀏覽器客戶端的,而計(jì)算機(jī)分配給瀏覽器的內(nèi)存及CPU占用是有限制的。雖說(shuō)瀏覽器引擎不斷地發(fā)展優(yōu)化,但是內(nèi)存占用多了, 性能不免會(huì)損耗。

內(nèi)存

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

性能

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

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

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

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

事件委托(事件代理)

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

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

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

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

移除多余的事件綁定

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

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

自定義事件

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

兩者不同的是CustomEvent可傳遞一個(gè)Object對(duì)象來(lái)傳輸數(shù)據(jù)。

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

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

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

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

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

天冷了,更文不易,望大家多多點(diǎn)贊。

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

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

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/99880.html

相關(guān)文章

  • 001-讀書(shū)筆記-JavaScript高級(jí)程序設(shè)計(jì) JavaScript簡(jiǎn)介

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

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

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

    k00baa 評(píng)論0 收藏0
  • 讀書(shū)筆記(04) - 錯(cuò)誤監(jiān)控 - JavaScript高級(jí)程序設(shè)計(jì)

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

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

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

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

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

    banana_pi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

tinylcy

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<