在DOM事件對(duì)象中有兩個(gè)屬性總是時(shí)不時(shí)的困擾我,就是target和currentTarget,有時(shí)候很迷惑分不清兩者的區(qū)別,因此有必要把這兩個(gè)屬性好好梳理一下,加深理解,以便日后的查詢(xún)。
MDN中對(duì)target的解釋為,一個(gè)觸發(fā)事件的對(duì)象的引用, 當(dāng)事件處理程序在事件的冒泡或捕獲階段被調(diào)用時(shí)。
而對(duì)于currentTarget,它指的是當(dāng)事件遍歷DOM時(shí),標(biāo)識(shí)事件的當(dāng)前目標(biāo)。它總是引用事件處理程序附加到的元素,而不是event.target,它標(biāo)識(shí)事件發(fā)生的元素。
舉個(gè)例子來(lái)說(shuō)明。
事件冒泡階段
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<ul>
<li>hello 1</li>
<li>hello 2</li>
<li>hello 3</li>
<li>hello 4</li>
</ul>
<script>
let ul = document.querySelectorAll('ul')[0]
let aLi = document.querySelectorAll('li')
ul.addEventListener('click',function(e){
let oLi1 = e.target
let oLi2 = e.currentTarget
console.log(oLi1) // 被點(diǎn)擊的li
console.log(oLi2) // ul
console.og(oLi1===oLi2) // false
})
</script>
</body>
</html>
我們知道,e.target可以用來(lái)實(shí)現(xiàn)事件委托,該原理是通過(guò)事件冒泡(或者事件捕獲)給父元素添加事件監(jiān)聽(tīng),e.target指向引發(fā)觸發(fā)事件的元素,如上述的例子中,e.target指向用戶(hù)點(diǎn)擊的li,由于事件冒泡,li的點(diǎn)擊事件冒泡到了ul上,通過(guò)給ul添加監(jiān)聽(tīng)事件而達(dá)到了給每一個(gè)li添加監(jiān)聽(tīng)事件的效果,而e.currentTarget指向的是給綁定事件監(jiān)聽(tīng)的那個(gè)對(duì)象,即ul,從這里可以發(fā)現(xiàn),e.currentTarget===this返回true,而e.target===this返回false。e.currenttarget和e.target是不相等的。
注意,在jQuery提供的on方法中,e.currentTarget與該方法接收的第二個(gè)參數(shù)有關(guān),根據(jù)jQuery的文檔描述
如果省略selector或者是null,那么事件處理程序被稱(chēng)為直接事件 或者 直接綁定事件 。每次選中的元素觸發(fā)事件時(shí),就會(huì)執(zhí)行處理程序,不管它直接綁定在元素上,還是從后代(內(nèi)部)元素冒泡到該元素的
當(dāng)提供selector參數(shù)時(shí),事件處理程序是指為委派事件(事件委托或事件代理)。事件不會(huì)在直接綁定的元素上觸發(fā),但當(dāng)selector參數(shù)選擇器匹配到后代(內(nèi)部元素)的時(shí)候,事件處理函數(shù)才會(huì)被觸發(fā)。jQuery 會(huì)從 event target 開(kāi)始向上層元素(例如,由最內(nèi)層元素到最外層元素)開(kāi)始冒泡,并且在傳播路徑上所有綁定了相同事件的元素若滿(mǎn)足匹配的選擇器,那么這些元素上的事件也會(huì)被觸發(fā)。
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
<style>
li{
padding: 5px;
border: 1px solid red;
}
span{
border: 1px solid #000;
}
</style>
</head>
<body>
<ul>
<li><span>hello 1</span></li>
<li><span>hello 1</span></li>
<li><span>hello 1</span></li>
<li><span>hello 1</span></li>
</ul>
<script>
let ul = document.querySelectorAll('ul')[0]
let aLi = document.querySelectorAll('li')
$('ul').on('click','li',function(e){
console.log(e.target) // 被點(diǎn)擊的元素
console.log(e.currentTarget) // li
console.log(e.currentTarget === this) // true
})
</script>
</body>
</html>
當(dāng)li中含有子元素的時(shí)候,e.target指的是觸發(fā)事件的元素,可能是span也可能是li,此時(shí)的e.currentTarget指的是selector那個(gè)參數(shù),也就是本例中的li。如果省略selector參數(shù),那么它和addEventListener中e.target和e.currentTarget是一致的。
事件目標(biāo)階段
我們知道,在DOM事件流中分為幾個(gè)不同的階段,如圖

上述例子是事件冒泡階段,
e.currenttarget和e.target是不相等的,但是在事件的目標(biāo)階段,e.currenttarget和e.target是相等的。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<ul>
<li>hello 1</li>
<li>hello 2</li>
<li>hello 3</li>
<li>hello 4</li>
</ul>
<script>
let ul = document.querySelectorAll('ul')[0]
let aLi = document.querySelectorAll('li')
for(let i=0;i<aLi.length;i++){
aLi[i].addEventListener('click',function(e){
let oLi1 = e.target
let oLi2 = e.currentTarget
console.log(oLi1) // li
console.log(oLi2) // li
console.og(oLi1===oLi2) // true
})
}
</script>
</body>
</html>
在本例中,事件的目標(biāo)階段即li,由于e.currentTarget始終指向添加監(jiān)聽(tīng)事件的那個(gè)對(duì)象,即aLi[i],也就是HTML中的li,而e.target指向觸發(fā)事件監(jiān)聽(tīng)的那個(gè)對(duì)象,也是li,因此e.target和e.currentTarget相等,同時(shí)也和this相等。
總結(jié)
因此不必記什么時(shí)候e.currentTarget和e.target相等,什么時(shí)候不等,理解兩者的究竟指向的是誰(shuí)即可。
-
e.target指向觸發(fā)事件監(jiān)聽(tīng)的對(duì)象。 -
e.currentTarget指向添加監(jiān)聽(tīng)事件的對(duì)象。