這是〈Svelte 從小白到入門〉系列的第十集,各集連結如下:


Action

Action 是客製 Svelte 元件內 HTML 元素行為的函式,利用 Svelte 提供的機制,賦予原生的 HTML 元素具有 action 函式的特性。

自訂事件

下面我們用 action 函式賦予 HTML 元素額外的事件特性,當原生的 HTML 事件不足以表示我們的元件邏輯時,可以用 action 自行定義元素的事件,當然也包括對原生事件的二次封裝,使元素與事件在邏輯上或語意上更加一致。

下面的橘色方塊,可以被滑鼠拖移(pan),放開後又會彈回中間,為此我們定義了一系列的 pan 事件在 pannable.js 裡,引用 pannable.js 後在 HTML 區域以 use:pannable 的語句使其作用在橘色方塊的 <div> 上,爾後橘色方塊就可以以 on: 語句聲明一系列 pan 事件所要觸發的函式:

打開 pannable.js 看看:

  • pnnable(node) 被餵了個 node,這是 action 函式的約定作法。因為在 HTML 內我們是對橘色方塊的 <div> 使用 use:pannable,所以這裡的 node 就是那個橘色方塊
  • 當滑鼠按下時,因為 node.addEventListener('mousedown', handleMousedown),觸發了 handleMousedown()
  • handleMousedown() 裡面又監聽了 mousemovemouseup 兩個原生事件,並觸發相對的函式
  • 在那些自訂的函式內,我們用 node.dispatchEvent(new CustomEvent()) 語句來建構與對外分派自訂事件
  • 最後的 destroy() 則是當 node 被銷毀時會被觸發的函式

當自訂事件作用在橘色方塊後,就可以用 on: 語句聲明這些自訂的 pan 事件所要觸發的函式。

Action 參數

要為一個 action 添加參數,語法與前面兩集提過的 transition、animation 一樣:

<button use:longpress="{duration}">press and hold</button>

如果要餵兩個參數,則把他們包成 JS 物件的形式:

<button use:longpress="{{duration, spiciness}}">
    press and hold
</button>

下面的範例中,滑桿的秒數會影響按鈕長按行為的秒數。

我們定義一個 duration,並將它與滑桿的值做綁定,再將 duration 作為參數餵給 longpress action:

在 longpress.js 內的結構,與前一個範例差不多,但注意到 retren 內多了一個 update(),此函式用於當 use:longpress="{duration}"{duration} 變化時 Svelte 會自動執行 update(),也就是說,當 update() 不存在時,duration 是不會自動更新的,這很不 reactivity…

小結

Action 是 Svelte 提供給我們自訂 HTML 元素行為的機制,它的聲明語法與 transition、animation 相似:

<button use:longpress="{{duration, spiciness}}">

而所謂的 Action 本身是一個有固定格式的函式:

  1. 此函式接受一個 node 參數,node 將會是調用此 action 的 HTML 元素,以上例來說就會是 <button>
  2. 當 action 的參數在外部被異動時,Svelte 會自動呼叫 action 內的 update(),我們可以在 update() 內為參數做更新
  3. node 被刪除時,Svelte 會自動呼叫 action 內的 destroy(),我們可以將不必要的物件或邏輯刪除