JS事件理解

先舉一個例子,有一個父節(jié)點parent包含了一個子節(jié)點child,如下:

.outer{
        border: 1px solid #ccc;
        padding: 10px;
}
.inner{
        border: 1px solid red;
        padding: 10px;
 }
<div id="parent" class='outer'>
        parent
        <div id="child" class='inner'>child</div>
 </div>
 const parentDom = document.getElementById('parent')
 const childDom = document.getElementById('child')
image.png

事件流理解

DOM事件流包括三個階段:

  • 事件捕獲:從最外層節(jié)點document逐級向下直到具體的事件對象,在該階段不會接收事件。
  • 處于目標階段:事件在該階段發(fā)生,并看成冒泡階段的一部分。
  • 事件冒泡:事件逐級向上傳播回文檔document。

如果對上述例子中的parent和child都定義click事件:

       parentDom.addEventListener('click', (e)=>{
            console.log('父節(jié)點點擊')
        })
        childDom.addEventListener('click', (e)=>{
            console.log('子節(jié)點點擊')
        })

如果點擊父節(jié)點,則只會調(diào)用父節(jié)點中定義的事件,打印內(nèi)容如下:


image.png

如果點擊子節(jié)點,則事件捕獲到具體的目標對象(子節(jié)點)后,調(diào)用對應(yīng)的事件,然后進入冒泡階段,父節(jié)點也會調(diào)用其click事件,因此打印內(nèi)容如下。


image.png

阻止事件冒泡

在上述問題中,如果我們點擊子節(jié)點時,只想觸發(fā)子節(jié)點的事件,不讓父節(jié)點的事件發(fā)生,則需要阻止事件冒泡。

        childDom.addEventListener('click', (e)=>{
            e.stopPropagation()
            console.log('子節(jié)點點擊')
        })

點擊子節(jié)點時,控制臺打印內(nèi)容:


image.png

如上所示,使用event對象的stopPropagation方法可以阻止事件冒泡,這樣就不會觸發(fā)父節(jié)點的click事件。
還有一個阻止事件冒泡的方法是stopImmediatePropagation,它與stopPropagation的區(qū)別為:

  • 如果對同一個元素綁定了多個event事件,則stopImmediatePropagation也會阻止該元素后面的event事件,而stopPropagation不會阻止同一個元素的后面的event事件。

如下,對childDom定義了兩個click事件的話,stopImmediatePropagation會阻止后面的事件調(diào)用,不會打印出 '子節(jié)點點擊第二次' ,而stopPropagation不會阻止,兩個都會打印。

        childDom.addEventListener('click', (e)=>{
            // e.stopPropagation()
            e.stopImmediatePropagation()
            console.log('子節(jié)點點擊第一次')
        })
        childDom.addEventListener('click', (e)=>{
            console.log('子節(jié)點點擊第二次')
        })

阻止事件的默認行為

有些事件會有一些默認的行為,比如a標簽點擊時會導(dǎo)航到href指定的url,如果想阻止這些默認行為,可以使用event的preventDefalut屬性。

<a href='' id='clickA'>點擊</a>
const aDom = document.getElementById('clickA')
aDom.addEventListener('click', (e)=>{
     e.preventDefault()
})

上述這個例子點擊a標簽時就不會出現(xiàn)頁面刷一下的情況。

target與currentTarget區(qū)別

target是事件的目標,即上述事件流中處于目標階段的DOM節(jié)點。currentTarget是綁定事件的DOM節(jié)點,其實可以想象為bindTarget。如下:

        parentDom.addEventListener('click', (e)=>{
            console.log(e.target,e.currentTarget)
            console.log('父節(jié)點點擊')
        })
        childDom.addEventListener('click', (e)=>{
            console.log('子節(jié)點點擊')
        })

則點擊子節(jié)點時,打印如下:


image.png

從上可知,target對象是child的DOM節(jié)點,而currentTarget是綁定事件的parent的DOM節(jié)點。

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

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