舉個(gè)栗子詳解事件代理

原文鏈接

為啥要使用事件代理

我們?cè)陂_(kāi)發(fā)中,可能會(huì)遇見(jiàn)這樣的需求:

在一個(gè)列表中點(diǎn)擊每個(gè)列表項(xiàng),將每個(gè)列表項(xiàng)中的內(nèi)容傳入某個(gè)函數(shù)中進(jìn)行處理。

通常結(jié)構(gòu)為

    <ul id="list">
        <li>msg</li>
        <li>msg1</li>
        <li>msg2</li>
        <li>msg3</li>
    </ul>

這里需要點(diǎn)擊某個(gè)列表項(xiàng),彈出他的內(nèi)容文本,不難寫(xiě)出下面的方法:

window.onload = () => {
            const ulNode = document.getElementById("list")
            const liNodes = ulNode.childNode || ulNode.children
            for (let i = 0; i < liNodes.length; i++) {
                liNodes[i].addEventListener('click', (e) => {
                        alert(e.target.innerHTML)
                    }, {
                        once: true
                    }) // once:在調(diào)用一次后被移除
            }
        }
效果如圖

然而,當(dāng)我們對(duì)這個(gè)大列表進(jìn)行dom操作時(shí),比如添加一個(gè)節(jié)點(diǎn),但上面的事件并沒(méi)有綁定到這個(gè)新節(jié)點(diǎn)上,需要我們?cè)俅握{(diào)用這個(gè)函數(shù),重新遍歷這些子節(jié)點(diǎn),綁定事件。


如圖

了解事件捕獲和冒泡

事件捕獲:當(dāng)某個(gè)元素觸發(fā)某個(gè)事件(如onclick),頂層對(duì)象document就會(huì)發(fā)出一個(gè)事件流,隨著DOM樹(shù)的節(jié)點(diǎn)向目標(biāo)元素節(jié)點(diǎn)流去,直到到達(dá)事件真正發(fā)生的目標(biāo)元素。在這個(gè)過(guò)程中,事件相應(yīng)的監(jiān)聽(tīng)函數(shù)是不會(huì)被觸發(fā)的。

事件目標(biāo):當(dāng)?shù)竭_(dá)目標(biāo)元素之后,執(zhí)行目標(biāo)元素該事件相應(yīng)的處理函數(shù)。如果沒(méi)有綁定監(jiān)聽(tīng)函數(shù),那就不執(zhí)行。

事件冒泡:從目標(biāo)元素開(kāi)始,往頂層元素傳播。途中如果有節(jié)點(diǎn)綁定了相應(yīng)的事件處理函數(shù),這些函數(shù)都會(huì)被一次觸發(fā)。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)來(lái)組織事件的冒泡傳播。

img

使用事件代理

當(dāng)子節(jié)點(diǎn)被點(diǎn)擊時(shí),click事件向上冒泡,父節(jié)點(diǎn)捕獲到事件后,我們判斷是否為所需的節(jié)點(diǎn),然后進(jìn)行處理。代碼如下:

       const ulNode = document.getElementById("list")
       ulNode.addEventListener('click',(e)=>{
            // e.target為當(dāng)前元素的子節(jié)點(diǎn),這里只對(duì)li元素進(jìn)行處理
            if(e.target&&e.target.nodeName.toLowerCase()==='li'){
                alert(e.target.innerHTML)
            }
       })

        const btn = document.getElementById('btn')
        btn.onclick = () => {
            const newLi=document.createElement('li')
            const text=document.createTextNode("new msg")
            newLi.appendChild(text)
            ulNode.appendChild(newLi)
        }
效果如圖

不需要再次為新節(jié)點(diǎn)綁定事件,照樣會(huì)響應(yīng)。

當(dāng)我們把新建的子節(jié)點(diǎn)改成p元素時(shí),

 const newLi=document.createElement('p')
如圖

因?yàn)樽隽伺袛?,所以點(diǎn)擊p元素是沒(méi)有響應(yīng)的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 總結(jié): 鼠標(biāo)事件 1.click與dbclick事件$ele.click()$ele.click(handler(...
    阿r阿r閱讀 1,724評(píng)論 2 10
  • (續(xù)jQuery基礎(chǔ)(1)) 第5章 DOM節(jié)點(diǎn)的復(fù)制與替換 (1)DOM拷貝clone() 克隆節(jié)點(diǎn)是DOM的常...
    凜0_0閱讀 1,526評(píng)論 0 8
  • 1. 事件冒泡與事件捕獲 事件冒泡和事件捕獲分別由微軟和網(wǎng)景公司提出,這兩個(gè)概念都是為了解決頁(yè)面中事件流(事件發(fā)生...
    cbw100閱讀 2,818評(píng)論 0 8
  • //響應(yīng)式表格 … //斑馬線(table-bordered table-hover t...
    西蘭花偉大炮閱讀 225評(píng)論 0 0
  • ?今日三件事(計(jì)劃) 1.讀書(shū)&筆記 2.圖書(shū)館講座 3.散步曬太陽(yáng) ?今日完成事項(xiàng)(總結(jié)) 1.171022【讀...
    水若_小水囈夢(mèng)閱讀 310評(píng)論 0 1

友情鏈接更多精彩內(nèi)容