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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

html点击冒泡事件,JavaScript 浏览器事件机制(捕获、冒泡、委托)

發(fā)布時(shí)間:2023/12/20 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 html点击冒泡事件,JavaScript 浏览器事件机制(捕获、冒泡、委托) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

DOM 樹(shù)

文檔對(duì)象模型 (DOM),我們把它簡(jiǎn)單的理解成一個(gè)對(duì)象const DOMTree = {}。它是瀏覽器的解析引擎把HTML文檔解析成相應(yīng)的JavaScript對(duì)象。

About elk

The truth about elk.

復(fù)制代碼

最終會(huì)解析成的樹(shù)狀結(jié)構(gòu)對(duì)象:

DOM 對(duì)象提供了一些接口讓我們可以對(duì)節(jié)點(diǎn)進(jìn)行增刪改查。并且還可以讓我們對(duì)節(jié)點(diǎn)進(jìn)行綁定事件。

例如我們可以對(duì)

節(jié)點(diǎn)綁定一個(gè)點(diǎn)擊事件。當(dāng)用戶觸發(fā)了點(diǎn)擊事件后,可以讓節(jié)點(diǎn)響應(yīng)一些事情。

DOM 事件

DOM 事件提供了人與web進(jìn)行交互的一種方式。

事件流

如果你單擊了某個(gè)按鈕,他們都認(rèn)為單擊事件不僅僅發(fā)生在按鈕上。換句話說(shuō),在單擊按鈕的同時(shí),你也單擊了按鈕的容器元素,甚至也單擊了整個(gè)頁(yè)面。

事件流描述的是從頁(yè)面中接收事件的順序。但有意思的是,IE和Netscape開(kāi)發(fā)團(tuán)隊(duì)居然提出了差不多是完全相反的事件流的概念。IE的事件流是事件冒泡流,而Netscape Communicator的事件流是事件捕獲流。

事件冒泡

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

點(diǎn)擊我

復(fù)制代碼

click 事件首先在

元素上發(fā)生,而這個(gè)元素就是我們單擊的元素。然后,click事件沿DOM樹(shù)向上傳播,在每一級(jí)節(jié)點(diǎn)上都會(huì)發(fā)生,直至傳播到document對(duì)象。圖片展示了事件冒泡的過(guò)程

[注意]所有現(xiàn)代瀏覽器都支持事件冒泡。

事件捕獲

事件捕獲的思想是不太具體的節(jié)點(diǎn)應(yīng)該更早接收到事件,而最具體的節(jié)點(diǎn)應(yīng)該最后接收到事件。事件捕獲的用意在于在事件到達(dá)預(yù)定目標(biāo)之前捕獲它。

在事件捕獲過(guò)程中,document對(duì)象首先接收到click事件,然后事件沿DOM樹(shù)依次向下,一直傳播到事件的實(shí)際目標(biāo),即

元素。圖片展示了事件捕獲的過(guò)程。

DOM 事件流

“DOM2級(jí)事件”規(guī)定的事件流包括三個(gè)階段:事件捕獲階段、處于目標(biāo)階段和事件冒泡階段。首先發(fā)生的是事件捕獲,為截獲事件提供了機(jī)會(huì)。然后是實(shí)際的目標(biāo)接收到事件。最后一個(gè)階段是冒泡階段,可以在這個(gè)階段對(duì)事件做出響應(yīng)。

在DOM事件流中,實(shí)際的目標(biāo)(

元素)在捕獲階段不會(huì)接收到事件。這意味著在捕獲階段,事件從document到再到后就停止了。

下一個(gè)階段是“處于目標(biāo)”階段,于是事件在

上發(fā)生,并在事件處理中被看成冒泡階段的一部分。

然后,冒泡階段發(fā)生,事件又傳播回文檔。

多數(shù)支持DOM事件流的瀏覽器都實(shí)現(xiàn)了一種特定的行為;即使“DOM2級(jí)事件”規(guī)范明確要求捕獲階段不會(huì)涉及事件目標(biāo),但I(xiàn)E9、Safari、Chrome、Firefox和Opera 9.5及更高版本都會(huì)在捕獲階段觸發(fā)事件對(duì)象上的事件。結(jié)果,就是有兩個(gè)機(jī)會(huì)在目標(biāo)對(duì)象上面操作事件。

[兼容]IE9、Opera、Firefox、Chrome和Safari都支持DOM事件流;IE8及更早版本不支持DOM事件流。

事件處理程序

事件就是用戶或?yàn)g覽器自身執(zhí)行的某種動(dòng)作。諸如 click、load 和 mouseover,都是事件的名字。 而響應(yīng)某個(gè)事件的函數(shù)就叫做事件處理程序(或事件偵聽(tīng)器)。

HTML 事件處理程序

復(fù)制代碼

html中定義的事件有權(quán)訪問(wèn)全局作用域中的任何代碼,例如外部引入的JS文件

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

以DOM0級(jí)方式添加的事件處理程序會(huì)在事件流的冒泡階段被處理

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

btn.onclick = function(){

alert("Clicked");

};

復(fù)制代碼

使用DOM0級(jí)方法指定的事件處理程序被認(rèn)為是元素的方法。因此,這時(shí)候的事件處理程序是在元素的作用域中運(yùn)行;

DOM0級(jí)事件處理程序的缺點(diǎn)是圍繞著每個(gè)事件目標(biāo)對(duì)于每種事件類型只能添加一個(gè)事件處理程序。

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

DOM2級(jí)事件處理程序定義了兩個(gè)方法用于處理指定和刪除事件處理程序的操作:addEventListener()和removeEventListener()

所有DOM節(jié)點(diǎn)中都包含這兩個(gè)方法,并且它們都接受3個(gè)參數(shù):要處理的事件名、作為事件處理程序的函數(shù)和一個(gè)布爾值。

最后的布爾值參數(shù)如果是true,表示在捕獲階段調(diào)用事件處理程序;如果是false,表示在冒泡階段調(diào)用事件處理程序。若最后的布爾值不填寫,則和false效果一樣

使用DOM2級(jí)事件處理程序的好處是可以添加多個(gè)事件處理程序,并按照他們添加的順序觸發(fā)

// 添加事件綁定

box.addEventListener("click",function(){

test('123');

},false);

function test(x){box.innerHTML += x;}

// 移除事件綁定

box.removeEventListener('click',test,false);

復(fù)制代碼

[兼容]IE9+、Firefox、Safari、Chrome和Opera支持DOM2級(jí)事件處理程序

DOM3級(jí)事件

在DOM2級(jí)事件的基礎(chǔ)上添加了更多的事件類型。

UI事件,當(dāng)用戶與頁(yè)面上的元素交互時(shí)觸發(fā),如:load、scroll

焦點(diǎn)事件,當(dāng)元素獲得或失去焦點(diǎn)時(shí)觸發(fā),如:blur、focus

鼠標(biāo)事件,當(dāng)用戶通過(guò)鼠標(biāo)在頁(yè)面執(zhí)行操作時(shí)觸發(fā)如:dblclick、mouseup

滾輪事件,當(dāng)使用鼠標(biāo)滾輪或類似設(shè)備時(shí)觸發(fā),如:mousewheel

文本事件,當(dāng)在文檔中輸入文本時(shí)觸發(fā),如:textInput

鍵盤事件,當(dāng)用戶通過(guò)鍵盤在頁(yè)面上執(zhí)行操作時(shí)觸發(fā),如:keydown、keypress

合成事件,當(dāng)為IME(輸入法編輯器)輸入字符時(shí)觸發(fā),如:compositionstart

變動(dòng)事件,當(dāng)?shù)讓覦OM結(jié)構(gòu)發(fā)生變化時(shí)觸發(fā),如:DOMsubtreeModified

同時(shí)DOM3級(jí)事件也允許使用者自定義一些事件。

IE中的DOM2級(jí)事件處理程序(<=IE8)

IE實(shí)現(xiàn)了與DOM中類似的兩個(gè)方法:attachEvent()和detachEvent()。

這兩個(gè)方法接受相同的兩個(gè)參數(shù):事件處理程序名稱與事件處理程序函數(shù)。

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

var handler = function(){

alert("Clicked");

};

// 綁定事件

btn.attachEvent("onclick", handler);

// 移除事件

btn.detachEvent("onclick", handler);

復(fù)制代碼

由于IE8及更早版本只支持事件冒泡,所以通過(guò)attachEvent()添加的事件處理程序都會(huì)被添加到冒泡階段。

attachEvent()的第一個(gè)參數(shù)是"onclick",而非addEventListener()方法中的"click"。

事件處理程序會(huì)在全局作用域中運(yùn)行,因此this等于window。

兼容IE低版本事件處理程序

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;

}

}

};

復(fù)制代碼

事件的 Event 對(duì)象

在觸發(fā)DOM上的某個(gè)事件時(shí),會(huì)產(chǎn)生一個(gè)事件對(duì)象event,這個(gè)對(duì)象中包含著所有與事件有關(guān)的信息。

包括導(dǎo)致事件的元素、事件的類型以及其他與特定事件相關(guān)的信息。例如,鼠標(biāo)操作導(dǎo)致的事件對(duì)象中,會(huì)包含鼠標(biāo)位置的信息,而鍵盤操作導(dǎo)致的事件對(duì)象中,會(huì)包含與按下的鍵有關(guān)的信息。所有瀏覽器都支持event對(duì)象,但支持方式不同。

兼容DOM的瀏覽器會(huì)將一個(gè)event對(duì)象傳入到事件處理程序中。無(wú)論指定事件處理程序時(shí)使用什么方法(DOM0級(jí)或DOM2級(jí)),都會(huì)傳入event對(duì)象。

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

btn.onclick = function(event){

alert(event.type); //"click"

};

btn.addEventListener("click", function(event){

alert(event.type); //"click"

}, false);

復(fù)制代碼

通過(guò)這個(gè)事件對(duì)象我們可以做一些事情:

阻止瀏覽器的默認(rèn)行為

阻止事件冒泡和捕獲

阻止瀏覽器的默認(rèn)行為

當(dāng)你點(diǎn)擊a標(biāo)簽時(shí),瀏覽器有一個(gè)默認(rèn)行為是跳轉(zhuǎn)鏈接。

當(dāng)我們想要自己去綁定事件,并且不讓這個(gè)默認(rèn)行為發(fā)生就叫阻止瀏覽器的默認(rèn)行為

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

a.addEventListener("click", function(event){

event.preventDefault();

// 事件處理程序內(nèi)容

}, false);

復(fù)制代碼

阻止事件冒泡和捕獲

前面已經(jīng)講了事件流的行為,那么當(dāng)我們只想在目標(biāo)階段處理這個(gè)click事件,并且不希望該事件冒泡或捕獲時(shí)可以阻止事件冒泡和捕獲

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

btn.onclick = function(event){

alert("Clicked");

event.stopPropagation(); // 阻止事件傳播

};

// document中雖然監(jiān)聽(tīng)了點(diǎn)擊事件,由于點(diǎn)擊btn時(shí)阻止了事件傳播,因此并不會(huì)冒泡到document上

document.body.onclick = function(event){

alert("Body clicked");

};

復(fù)制代碼

事件的內(nèi)存和性能

在JavaScript中,添加到頁(yè)面上的事件處理程序數(shù)量將直接關(guān)系到頁(yè)面的整體運(yùn)行性能。導(dǎo)致這一問(wèn)題的原因是多方面的。首先,每個(gè)函數(shù)都是對(duì)象,都會(huì)占用內(nèi)存;內(nèi)存中的對(duì)象越多,性能就越差。

事件委托

對(duì)“事件處理程序過(guò)多”問(wèn)題的解決方案就是事件委托。事件委托利用了事件冒泡,只指定一個(gè)事件處理程序,就可以管理某一類型的所有事件。例如,click事件會(huì)一直冒泡到document層次。也就是說(shuō),我們可以為整個(gè)頁(yè)面指定一個(gè)onclick事件處理程序,而不必給每個(gè)可單擊的元素分別添加事件處理程序。

復(fù)制代碼

為3個(gè)li都添加相應(yīng)的點(diǎn)擊事件,這樣會(huì)導(dǎo)致性能更差,我們可以只在ul上面添加一個(gè)點(diǎn)擊事件,利用冒泡原理來(lái)處理事件

var list = document.getElementById("myLinks");

EventUtil.addHandler(list, "click", function(event){

switch(event.target.id){

case "doSomething":

document.title = "I changed the document's title";

break;

case "goSomewhere":

location.href = "http://www.wrox.com";

break;

case "sayHi":

alert("hi");

break;

}

});

復(fù)制代碼

事實(shí)上React中的事件處理程序都是采用的事件委托的方式。

總結(jié)

以上是生活随笔為你收集整理的html点击冒泡事件,JavaScript 浏览器事件机制(捕获、冒泡、委托)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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