事件

JavaScript是一個以事件驅動(Event-driven)的程式語言,藉由事件的觸發動作(滑鼠點按、鍵盤輸入等等)或是感應器的訊息,來啟動整體的程式流程。

在JavaScript中有一個不斷偵測事件發生的事件迴圈(Event Loop),所有在網頁上的DOM元素註冊的事件,都會進入一個佇列(queue)中,等待被觸發事件

DOM事件

  • DOM(Document Object Model, 文件物件模型)把HTML、XHTML、XML文件的視為樹狀的結構,每個節點都是代表文件的一個物件。

  • 可以註冊各種事件處理器/監聽器(event handlers/listeners)在DOM的節點元素上

Event物件(介面)

Event物件屬性(以下屬性都是只能讀不能寫):

  • currentTarget: 目前的事件對象。

    W3C標準的定義中,this會相等於event.currentTarget

  • target: 分派事件的原始對象

    event.target永遠指向觸發事件的那個元素

  • type: 事件的類型,共有數十種

  • bubbles: 冒泡狀態,布林值,true代表會在DOM中往上冒泡

  • cancelable: 事件是否為可取消的,布林值

    cancelable則是代表可否使用stopPropagation()方法。

Event物件方法:

  • preventDefault(): 取消事件的行為(需為可取消的事件),但無法阻止事件的傳播(propagation)

  • stopPropagation(): 停止事件的傳播行為

事件處理模型

  • 內聯模型:程式碼寫在HTML中

<button onclick="console.log('hello!');"> Say Hello! </button>
  • W3C方式(W3C Way)模型

const el = document.getElementById('myButton')

el.addEventListener( 'click', function(){
     console.log('hello!')
}, false)

事件監聽的方式可以對一個元件附加多個事件處理函式,有三種方法可使用:

  • addEventListener: 在事件對象上加入事件監聽者

  • removeEventListener: 從事件對象移除事件監聽者

  • dispatchEvent: 送出事件給所有有訂閱的監聽者

事件的冒泡、捕捉

  • 事件的冒泡(往上冒泡)與捕捉(往下捕捉)是兩種事件在DOM中的傳播(propagation)的方式。

  • 事件冒泡(bubbling)的情況時,當最內部的元素被觸發事件時,會先執行自己本身的事件處理函式,然後才會執行上層父母元素的事件處理函式。

有些幾個事件並沒有支援事件的傳播,例如onfocus或onblur。 那麼要如何控制使用哪一種?一般都是使用事件監聽的方法,以傳入參數值作控制,也就是addEventListener方法的最後一個參數phase(階段)來決定。 phase(階段)是一個布林值,如果是false就用事件冒泡(bubbling),如果是true就使用事件捕捉(capturing)。預設沒寫的話,就是false,也就是預設使用事件冒泡(bubbling)機制。

自訂事件

例如會員登入時想要用個會員登入事件,聊天室程式常見的好友上線時的好友上線事件,這就是自訂事件的功用了。

//'userLogin'是這個自訂事件的名稱
//detail物件中的屬性是額外的屬性。bubbles與cancelable是可以定義也可以不需要定義的屬性,沒定義會使用預設值false

//自訂事件
const myEvent = new CustomEvent(
  'userLogin',
  {
    detail: {
              message: 'Hello World!',
              time: new Date(),
          },
          bubbles: true,
          cancelable: true
  }
)

//設定EventTarget物件(介面)
const myButton = document.getElementById('myButton')

//使用自訂事件
myButton.addEventListener('userLogin', function(e) {
    console.log('Event is: ', e)
    console.log('Custom data is: ', e.detail)
})

Last updated