JS 事件捕獲、事件冒泡以及事件委託圖文詳解
核心:JS的點選事件會先一層一層捕獲到target元素,然後再從target元素沿著路徑一層層向上冒泡
最重要的就是理解它的路徑
測試介面:
這裡先展示一下路徑的形式(以點選測試介面的son為例子)
通過這個path幫助我們理解事件捕獲以及事件冒泡:當我們點選了son之後,瀏覽器先從window一層一層向下找,最終找到我們的son,這個階段稱為事件捕獲階段,捕獲結束後,就從target son 一層一層向window冒泡,這個階段稱之為事件冒泡。
我們預設的監聽事件都是在冒泡階段執行的,要想在捕獲階段執行則需要給監聽函式的第三個引數賦為true。
從圖中我們也可以看到cancleBubble && cancelable && defaultPrevent
cancelable的truith代表我們是否可以取消冒泡
cancleBubble的truith代表我們是否取消了冒泡
defaultPrevent的truith代表我們是否禁止預設行為
(題外話,最新版瀏覽器基本都支援passive,在passive為true的監聽事件裡呼叫preventDefault會失效,而且在監聽touchstart以及touchmove裡預設都是passive:true,所以想要在監聽函式裡呼叫preventDefault()禁止頁面滾動需要addEventListener的第三個引數為{passive:false},這裡的passive主要是為了提升效能,google做過資料調查只有20%的監聽函式裡會呼叫preventDefault,所以為了效能提升,就不等待監聽函式的執行而是直接預設為你不禁止預設行為,從而讓使用者滑動的時候不會感覺到卡頓)
在handler中,我們可以呼叫stopPropagation去阻止冒泡或者捕獲(取決於你的處理函式執行在哪個階段,路徑上所有的target都可以阻止瀏覽器繼續傳播事件,也就是說我點選了son,但是在father的捕獲階段就stopPropagation,則son的handler就永遠不會執行了,因為它根本沒有接收到click事件)
通過事件冒泡以及事件捕獲,我們就可以實現事件委託了
事件委託的概念:通過動態生成的元素,一開始並不在dom樹上,所以不可以直接通過querySelector選擇然後監聽,於是通過監聽它的父節點去間接監聽我們的預期target。
我們知道,當我們點選了target後,它會一層一層捕獲然後又一層層冒泡,那麼我們就可以在它的路徑上(也就是監聽它的任一父節點)判斷target是不是我們的預期target(通過判斷標籤、class以及ID等方式去區別),是的話我們就執行handler,不是的話就不做處理。通俗點來說就是我不知道你什麼時候回家,但是我知道你爸爸肯定知道你什麼時候回家,那我只需要將handler交給你爸,當你爸知道你回家之後就去執行handler