點燈坊

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

使用 Once Event Modifier 只觸發 Event 一次

Sam Xiao's Avatar 2021-04-30

實務上有些需求只希望 User 只能 Click Button 一次,之後任何 Click 都忽略不計,此時可使用 once Event Modifier 達成。

Version

Vue 3.0.11

Vanilla JavaScript

once000

無論 + 被按幾次,count 都只遞增到 1 就停止。

<template lang='pug'>
button(@click='onClick') +
span {{ count }}
</template>

<script setup>
ref: isClicked = false
ref: count = 0

let onClick = () => {
  if (isClicked) return

  isClicked = true
  count++
}
</script>

第 7 行

ref: count = 0
ref: isClicked = false
  • isClicked:判斷 button 是否第一次被 click
  • count:負責遞增 counter 與顯示

10 行

let onClick = () => {
  if (isClicked) return

  isClicked = true
  count++
}

首先判斷 isClicked state 是否為 true,若已經被 click 過則 return 結束。

Once Event Modifier

once000

結果不變,但使用 once event modifier 改寫。

<template lang='pug'>
button(@click.once='onClick') +
span {{ count }}
</template>

<script setup>
ref: count = 0

let onClick = () => count++
</script>

第 2 行

button(@click.once='onClick') +

click 之後加上 once event modifier 之後,onClick() 只會被 trigger 一次,因此不必再搭配 isClicked state 判斷。

第 9 行

let onClick = () => count++

只需實現對 count state 遞增即可,不用判斷是否已經被 click 過。

Point-free

once000

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

<template lang='pug'>
button(@click.once='onClick') +
span {{ count }}
</template>

<script setup>
import { ref } from 'vue'
import { read, write } from 'vue3-fp'
import { pipe, inc } from 'ramda'

let count = ref(0)

let onClick = pipe(
  read(count),
  inc,
  write(count)
)
</script>

13 行

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

使用 pipe() 組合 onClick()

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

Conclusion

  • 若使用 Vanilla JavaScript 實現,還需要搭配另外一個 state 控制是否 click 過
  • 使用 once event modifier 讓 HTML 意圖更明顯,且 JavaScript 也不必另外維護 state

Reference

Vue, Event Modifier