怎麼觸發子級的點選事件_JS的事件委託
阿新 • • 發佈:2021-01-19
技術標籤:怎麼觸發子級的點選事件
引言:遇到下面應用場景,你要怎麼辦?
場景一:
我們要給100個按鈕新增點選事件,怎麼辦?
最笨的辦法:直接給100個按鈕都addEventListener
但是有了事件委託後:監聽這100個按鈕的祖先,等冒泡的時候,判斷target是不是這100個按鈕中的一個 就可以了
場景二:
我們要監聽目前不存在的元素的點選事件,咋辦?
有了事件委託:監聽祖先,等到冒泡時,判斷點選的元素是不是我想要監聽的元素就可以了。
事件委託這麼牛,那他到底是什麼,怎麼實現的呢?別急,往下看。。。
一、什麼是事件委託?有什麼好處?
事件委託是指利用冒泡原理,把事件加到父級上,觸發執行效果。
由於冒泡階段,瀏覽器從使用者點選的內容從下往上遍歷至 window,逐個觸發事件處理函式,
因此可以監聽一個祖先節點(例如爸爸節點、爺爺節點)來同時處理多個子節點的事件。
好處:
- 減少事件數量,提高效能。
- 預測未來元素,新新增的元素仍然可以觸發該事件。
---聽起來不錯,拉出來看看?
---好的,展示!
程式碼一:“實現10(或者更多)個按鈕,繫結click事件,按下後能夠返回按的是第幾個”
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div id="zxm"> <button data-id='1'>click1</button> <button data-id='2'>click2</button> <button data-id='3'>click3</button> <button data-id='4'>click4</button> <button data-id='5'>click5</button> <button data-id='6'>click6</button> <button data-id='7'>click7</button> <button data-id='8'>click8</button> <button data-id='9'>click9</button> <button data-id='10'>click10</button> </div> </body> </html>
JS程式碼:
zxm.addEventListener('click',(e) =>{
const t = e.target
if(t.tagName.toLowerCase()==='button'){
console.log('data-id 是'+ t.dataset.id)
}
})
輸出結果:
程式碼二:監聽所有的li標籤,如果使用者點選li標籤,就console.log('使用者點選了Li標籤')
<ul id="test"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul>
JS程式碼:
// 監聽父元素 ul#test
test.addEventListener('click', (e)=> {
//通過瀏覽器傳進來的e引數,找到當前點選元素
const t = e.target
// 判斷當前元素是不是Li標籤
if(t.matches('li') {
console.log('使用者點選了li')
}
})
實現思路就是:
首先監聽父元素,
然後根據瀏覽器傳進去的事件資訊,拿到當前點選元素,
再判斷當前點選元素是不是li元素, 如果是,就console.log('使用者點選Li標籤')
JS 實現封裝
on('click', '#test', 'li', ()=>{
console.log('使用者點選了li')
})
function on(eventType, element, selector, fn) {
// 先判斷是不是element,
//如果傳進來的是選擇器,不是element本身,就先變成element,
// 因為只有element才能監聽事件
if (!(element instanceof Element)) {
element = document.querySelector(element)
}
element.addEventListener(eventType, (e)=>{
let target = e.target
if (target.matches(selector)) {
fn(e)
}
})
}
完整展示
JS Binjs.jirengu.com但是以上這種實現有一個小問題,那就是如果被點選元素有多個父元素怎麼辦?
<ul id="test">
<li>
<p>
<span>1</span>
</p>
</li>
<li>
<p>
<span>2</span>
</p>
</li>
<li>
<p>
<span>3</span>
</p>
</li>
<li>
<p>
<span>4</span>
</p>
</li>
</ul>
JS程式碼
遞迴地向上多找幾層父節點,直到找到li標籤,
同時還必須限定,尋找的範圍不能超過 element,
拿上面的例子來說,不可以越過ul標籤,去找body標籤
on('click', '#test', 'li', ()=>{
console.log('使用者點選了li')
})
function on(eventType, element, selector, fn) {
if (!(element instanceof Element)) {
element = document.querySelector(element)
}
element.addEventListener(eventType, (e)=>{
let el = e.target
// 如果匹配到了selector就跳出迴圈
while(!el.matches(selector)){
if (el === element){
//已經找到了父元素,說明還沒找到,就設定為null
el = null
break
}
el = el.parentNode
}
// 找到了el, 就呼叫函式
el && fn.call(el, e, el)
})
return element
}
完整展示:
JS Binjs.jirengu.com二、再來回顧一下:
事件委託是指利用冒泡原理,把事件加到父級上,觸發執行效果。
由於冒泡階段,瀏覽器從使用者點選的內容從下往上遍歷至 window,逐個觸發事件處理函式,
因此可以監聽一個祖先節點(例如爸爸節點、爺爺節點)來同時處理多個子節點的事件。
好處:
- 減少事件數量,提高效能。
- 預測未來元素,新新增的元素仍然可以觸發該事件。