基于事件冒泡、事件捕獲和事件委托詳解_第1頁
基于事件冒泡、事件捕獲和事件委托詳解_第2頁
基于事件冒泡、事件捕獲和事件委托詳解_第3頁
基于事件冒泡、事件捕獲和事件委托詳解_第4頁
基于事件冒泡、事件捕獲和事件委托詳解_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第基于事件冒泡、事件捕獲和事件委托詳解事件冒泡、事件捕獲和事件委托

在javascript里,事件委托是很重要的一個東西,事件委托依靠的就是事件冒泡和捕獲的機(jī)制,我先來解釋一下事件冒泡和事件捕獲:

事件冒泡會從當(dāng)前觸發(fā)的事件目標(biāo)一級一級往上傳遞,依次觸發(fā),直到document為止。

事件捕獲會從document開始觸發(fā),一級一級往下傳遞,依次觸發(fā),直到真正事件目標(biāo)為止。

這么說是不是很抽象,其實就像我敲擊了一下鍵盤,我在敲擊鍵盤的同時,我是不是也敲擊了這臺電腦,我寫個例子大家就明白了:

!DOCTYPEhtml

html

head

metacharset="UTF-8"

title/title

/head

styletype="text/css"

#box1{width:300px;height:300px;background:blueviolet;}

#box2{width:200px;height:200px;background:aquamarine;}

#box3{width:100px;height:100px;background:tomato;}

div{overflow:hidden;margin:50pxauto;}

/style

body

divid="box1"

divid="box2"

divid="box3"/div

/div

/div

script

functionsayBox3(){

console.log('你點(diǎn)了最里面的box');

functionsayBox2(){

console.log('你點(diǎn)了最中間的box');

functionsayBox1(){

console.log('你點(diǎn)了最外面的box');

//事件監(jiān)聽,第三個參數(shù)是布爾值,默認(rèn)false,false是事件冒泡,true是事件捕獲

document.getElementById('box3').addEventListener('click',sayBox3,false);

document.getElementById('box2').addEventListener('click',sayBox2,false);

document.getElementById('box1').addEventListener('click',sayBox1,false);

/script

/body

/html

我們畫了三個box,結(jié)構(gòu)是父子關(guān)系,分別綁定了打印事件,現(xiàn)在我們來點(diǎn)擊最中間的紅色box:

我們發(fā)現(xiàn),我們僅僅是點(diǎn)擊了紅色的box,但是綠色和紫色的box也被觸發(fā)了打印事件,觸犯順序是紅色綠色紫色,這種現(xiàn)象就是事件冒泡了。

我們再試試事件捕獲,把上面代碼里監(jiān)聽事件的第三個參數(shù)改為true,然后點(diǎn)擊紅色的box:

我們還是只點(diǎn)擊最中間的紅色box,和上一次一樣,也是三個box都觸發(fā)了事件,但是順序反過來了,紫色綠色紅色,這種現(xiàn)象稱為事件捕獲。

通過上面的例子,應(yīng)該很容易就理解了事件冒泡和事件捕獲,我們平時都是默認(rèn)冒泡的,冒泡是一直冒到document根文檔為止。

現(xiàn)在來談?wù)勈录?,事件委托又稱之為事件代理,我們通過一個通俗的例子來解釋:

有三個同事預(yù)計會在周一收到快遞,為了簽收快遞,有兩種辦法:1.三個人在公司門口等快遞;2.委托給前臺MM代為簽收?,F(xiàn)實當(dāng)中,我們大都采用委托的方案(公司也不會容忍那么多員工站在門口就為了等快遞)。前臺MM收到快遞后,她會判斷收件人是誰,然后按照收件人的要求簽收,甚至代為付款。這種方案還有一個優(yōu)勢,那就是即使公司里來了新員工(不管多少),前臺MM也會在收到寄給新員工的快遞后核實并代為簽收(可以給暫時不存在的節(jié)點(diǎn)也綁定上事件)。

我們再舉另一個例子:

現(xiàn)在有一個ul,ul里又有100個li,我想給這100個li都綁定一個點(diǎn)擊事件,我們一般可以通過for循環(huán)來綁定,但是要是有1000個li呢?為了提高效率和速度,所以我們這時可以采用事件委托,只給ul綁定一個事件,根據(jù)事件冒泡的規(guī)則,只要你點(diǎn)了ul里的每一個li,都會觸發(fā)ul的綁定事件,我們在ul綁定事件的函數(shù)里通過一些判斷,就可以給這100li都觸發(fā)點(diǎn)擊事件了。

具體怎么實現(xiàn),看代碼:

//這里不講IE,結(jié)尾再說

functionclickLi(){

alert('你點(diǎn)擊了li');

document.getElementById('isUl').addEventListener('click',function(event){

//每一個函數(shù)內(nèi)都有一個event事件對象,它有一個target屬性,指向事件源

varsrc=event.target;

//我們判斷如果target事件源的節(jié)點(diǎn)名字是li,那就執(zhí)行這個函數(shù)

//target里面的屬性是非常多的,id名、class名、節(jié)點(diǎn)名等等都可以取到

if(src.nodeName.toLowerCase()=='li'){

clickLi();

});

這樣我們就通過給ul綁定一個點(diǎn)擊事件,讓所有的li都觸發(fā)了函數(shù)。

那如果想給不同的li綁定不同的函數(shù)怎么辦?

假設(shè)有3個li,我們先寫3個不同的函數(shù),再給3個li設(shè)置不同的id名,通過判斷id名是不是就能給不同的li綁定不同的函數(shù)啦:

body

ulid="isUl"

liid="li01"1/li

liid="li02"2/li

liid="li03"3/li

/ul

script

functionclickLi01(){

alert('你點(diǎn)擊了第1個li');

functionclickLi02(){

alert('你點(diǎn)擊了第2個li');

functionclickLi03(){

alert('你點(diǎn)擊了第3個li');

document.getElementById('isUl').addEventListener('click',function(event){

varsrcID=event.target.id;

if(srcID=='li01'){

clickLi01();

}elseif(srcID=='li02'){

clickLi02();

}elseif(srcID=='li03'){

clickLi03();

/script

/body

這就是所謂的事件委托,通過監(jiān)聽一個父元素,來給不同的子元素綁定事件,減少監(jiān)聽次數(shù),從而提升速度。

那么,能不能阻止元素的事件冒泡呢,答案是可以的。

一開始那個例子,假如我們真的只想點(diǎn)擊最里面的那個紅色box,不想另外兩個box的事件被觸發(fā),我們可以在給紅色box綁定事件的函數(shù)里這么寫:

functionsayBox3(event){

//阻止冒泡

event.stopPropagation();

console.log('你點(diǎn)了最里面的box');

document.getElementById('box3').addEventListener('click',sayBox3,false);

這樣我們再點(diǎn)擊紅色的box,那就只會觸發(fā)它本身的事件啦。

那阻止冒泡有沒有實際用途呢?答案是有的,我們看這個例子:

這是一個模態(tài)框,現(xiàn)在的需求是當(dāng)我們點(diǎn)擊紅色的按鈕需要跳轉(zhuǎn)頁面,然后點(diǎn)擊白色的對話框不需要任何反應(yīng),點(diǎn)其它任何地方就關(guān)閉這個模態(tài)框。

這里就需要用到阻止冒泡了,紅色的按鈕是白色對話框的子元素,白色對話框又是這整個模態(tài)框的子元素,我們給模態(tài)框加上一個點(diǎn)擊事件關(guān)閉,然后給紅色的按鈕加上一個點(diǎn)擊事件跳轉(zhuǎn),這時就產(chǎn)生了一個問題,只要點(diǎn)擊白色的對話框,由于冒泡機(jī)制,這個模態(tài)框也會關(guān)閉,實際上我們并不想點(diǎn)擊白色的對話框有任何反應(yīng),這時我們就給這個白色的對話框綁定一個點(diǎn)擊事件,函數(shù)里寫上event.stopPropagation();,這樣就OK了。

老版本的IE存在兼容問題,根本不支持addEventListener()的添加事件和removeEventListener()的刪除事件,它有自己的監(jiān)聽方法:

//添加事件,事件流固定為冒泡

attachEvent(事件名,事件處理函數(shù))

//刪除事件

detachEvent(事件名,事件處理函數(shù))

還有IE里的事件對象是window.event,事件源是srcElement,阻止冒泡寫法也不一樣:

function(){

//IE里阻止冒泡

window.event.cancelBubble=true;

//IE里獲取事件源的id

varsrcID=window.event.srcElement.id;

function(event){

//非IE里阻止冒泡

event.stopPropagation();

//非IE里獲取事件源的id

varsrcID=event.target.id;

}

關(guān)于js的瀏覽器兼容問題,一般用能力檢測來解決,if(){}else{}

我們平時工作一般都是用jq

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論