JS是一個「事件驅動」的程式語言,必須等到事件被觸發後,才會去執行相對應的內容。
事件機制的原理
事件觸發->去做相對應的內容
事件流程
網頁元素接收事件的順序
分別有以下兩種:
Event Capturing: 事件捕獲 -從document,由上往下傳遞,直到找到啟動元素為止。
Event Bubbling: 事件冒泡 - 從觸發事件的目標元素,由下往上傳遞,直到找到document為止。
那在addEventListener
的事件監聽的第三個參數,true
代表捕獲,false
代表冒泡。
事件傳遞
我覺得在事件流程中的捕獲和冒泡的機制,我最不習慣的是事件會傳遞的部分。阿不就點到誰就該由誰跳出來嗎(誤XDD)
在JS中,事件會因為捕獲和冒泡的機制而往上傳遞 或 往下傳遞,那這類的應用在本章的最後面的事件指派的部分,
你就會感受到事件傳遞的麻煩,阿不是,是事件傳遞的威力囉~~
事件的註冊綁定
on-event(HTML屬性)
直接在html文件中,直接在目標元素上的html標籤綁定觸發事件。
ex:
1 | ---HTML--- |
on-event(非HTML屬性)
ex:
1 | ---HTML--- |
addEventListener 事件監聽
用這種方式註冊事件的好處是可以同時對同一個元素綁定多個事件。
像下面這個範例
1 | ---HTML--- |
網頁事件
網頁介面事件
onload事件
它是註冊在windo物件上,這個事件的意思是網頁內的資源全數載入之後,才會觸發onload事件裡面的內容。
在我做過的專案檔中,像是口罩地圖,就會希望在圖資在入完成後,觸發後續的內容,故我們就會對這個圖資使用onload事件喔~
error事件
書中提到了這個我不太常用的事件,但是,我覺得還蠻好用的。
作者提到,這個是一個很適合用on-event 的方式做註冊的事件,也就是直接寫在該物件的HTML標籤上。
使用時機建議在img
元件,當圖片在入失敗後,就會觸發綁定的onerror事件,跳出圖片載入應該呈現的圖片,
好讓使用者知道,這張圖片載入失敗了。
書中也特別註明了,如果你將這個圖片的onerror寫在onload事件裡面的話是會沒有任何效果的喔,因為,圖片的錯誤已經發生了,
等到全部的網頁資源都入完成後,才將onerror事件掛在在那的圖片元件上的話,就沒有任何意義了。
隱藏在事件中的event
當我們利用addEventListener
去註冊一個事件的時候,Event Listener會去註冊一個「事件物件」,而這個事件物件會包含與這個
事件所有相關的內容,而這個「事件物件」就是隱藏在事件中的event,他會以參數的方式傳入你所註冊的addEventListener,此時,
你就可以透過它來觀察觸發元素的種種行為或內容。
target
這個功能我自己蠻常用到的,在我自己的部落格中的這一篇有介紹到e.target
的使用方式,
我們時常會透過它來得到觸發該事件元素的內容文字阿 或是 它的標籤屬性等等的內容,還蠻好用的。
阻止事件冒泡event.stopPropagation()
這邊的話,書中有提到一個蠻實用的例子。
在一般的label
和 input
的組合會像下面醬:
1 | <label for="xxx">Output</label> |
但是,有時候會因為排版的問題我們會將上面的排版改成下面這種寫法
1 | <label class="lbl"> |
功能完全一樣,但是,排版的部分我個人是覺得下面的寫法label和checkbox高度部分會比較對齊。
但是,用下面這種寫法會有事件冒泡的問題,也就是當我們按下label的時候,checkbox會因為事件冒泡的關係,
連帶的也觸發了click事件。
那我們想要防止這種觸發兩次label
的click的狀況,我們就需要使用到stopPropagation
囉。
以上這個範例,就可以看到,我們是在checkbox上加入stopPropagation
喔,並不是加在label
上面。
如此一來,就可以防止checkbox再次觸發了label的click事件囉。
阻擋預設行為 event.preventDefault()
在網頁中的a
連結 和 form
表單的提交的預設行為,我們就可以利用event.preventDefault()
來取消這些預設行為。
1 | ---HTML--- |
以上這個範例,我們在a連結的點擊事件中加入了event.preventDefault()
就可以取消原本會跳轉到Google頁面的效果囉~~
不要搞混event.preventDefault() 和 event.stopPropagation()
不要搞混致這兩個功能的功用喔~ 一個是用來阻止冒泡的機制 另一個是阻止該元素的預設行為的。
在事件中找回「自己」- this
書中特別提到了this
是代表e.currentTarget
,也就是「觸發事件的目標元素」,
而e.target
是代表「觸發事件的元素」,
它們兩者會產生差別的時機是在於,當該事件會有事件冒泡的狀況的時候,他們兩個人所代表的元素是會有不一樣的時候的,
但如果沒有事件冒泡的話,他們兩個其實沒差,代表的對象都是一樣的。
事件指派 - 監聽父元素
在這邊書中有提到了一個實用的例子,也是我在專案中常用的方法。
若今天在ul中,有多個li子元素,我們想要為這些li子元素都綁定click事件,那這個時機,我們就可以利用監聽父元素ul,
接著,利用事件冒泡的事件傳遞機制來為這些子元素綁上click事件。
1 | ---HTML--- |
以上這個範例,我們將click的監聽事件綁定在父元素ul上面,當我們點擊了ul父元素,接著,等待事件從它的子元素里冒泡上来,
並可以知道這個事件是從哪個元素觸發的,如此一來,就達成為所有子元素綁定了click事件的目的囉。