點燈坊

失くすものさえない今が強くなるチャンスよ

使用 guard 建立 Watch

Sam Xiao's Avatar 2021-08-24

Vue 3 以 watch 讀取 State,但這種方式不方便 Point-free,Vue3-fp 提供了 Curry Function 版本的 guard

Version

Vue 3.2
Vue3-fp 0.3.2

Composition API

guard000

每秒鐘更新 counter,一旦 counter 更新就馬上 console.log 顯示。

<template>
  {{ count }}
</template>

<script setup>
import { watch } from 'vue'

let count = $ref (0)

setInterval (_ => count++, 1000)
watch (count, x => console.log(x))  
</script>

10 行

setInterval (_ => count++, 1000)

每一秒對 count state 遞增。

11 行

watch (count, x => console.log(x))
  • watch 第一個 argument 傳入要監視的 state

  • watch 第二個 argument 傳入要執行的 function

Point-free

guard000

結果不變,但使用 Point-free 改寫。

<template>
  {{ count }}
</template>

<script setup>
import { ref, watch } from 'vue'
import { read, write } from 'vue3-fp'
import { pipe, inc, always as K } from 'ramda'
import { log, interval } from 'wink-fp'
  
let guard = ref => f => watch (ref, f)  

let count = ref (0)

let incCount = pipe (
  read (count),
  inc,
  write (count)
)

pipe (
  K (incCount),
  interval (1000),
  K (log),
  guard (count)
) ()
</script>

11 行

let guard = ref => f => watch (ref, f)

guard 為 Point-free 版本的 watch

15 行

let incCount = pipe (
  read (count),
  inc,
  write (count)
)

使用 pipe 組合 incCount

  • read (count):讀取 count state
  • inc:對值遞增
  • write (count):寫入 count state

21 行

pipe (
  K (incCount),
  interval (1000),
  K (log),
  guard (count)
) ()

使用 pipe 組合 IIFE:

  • K (incCount):準備 incCount 傳入 interval(1000)
  • interval (1000):每 1 秒鐘執行 incCount
  • K (log):準備 log 傳入 guard(count)
  • guard (count):當 count state 有改變則執行 log

Vue3-fp

guard000

結果不變,但使用 Vue3-fp 改寫。

<template>
  {{ count }}
</template>

<script setup>
import { ref } from 'vue'
import { read, write, guard } from 'vue3-fp'
import { pipe, inc, always as K } from 'ramda'
import { log, interval } from 'wink-fp'

let count = ref (0)

let incCount = pipe (
  read (count),
  inc,
  write (count)
)

pipe (
  K (incCount),
  interval (1000),
  K (log),
  guard (count)
) ()
</script>

第 7 行

import { read, write, guard } from 'vue3-fp'

Vue3-fp 已經內建 guard() 可直接使用。

guard :: Ref a -> () -> * -> Void
Point-free 版本的 watch

Ref a:傳入 state

() -> *:傳入當 state 改變時要執行的 function

Void:不回傳任何值

Conclusion

  • watch 雖然是傳入 function,但由於其不是 curry function 因此不方便 Point-free 使用,可使用 guard 取代