vue3でのカウントダウンタイマーの実装

クイズアプリ実装時の時間設定

vue3 Composition APIでのカウントダウンタイマーの実装を行ったので
自分が再度実装するときの記事として残しておきます。
javascriptなどでは情報があったのですがvueでは探しても見つからなかったので。

実装条件

  1. カウントダウンは6分。
  2. 分、秒でカウントをしていき、5分00秒→4分59秒のようになる。

まずは全体コードを記載します。

script
import { ref, computed, onMounted } from 'vue'

const minutes = ref(6)
const seconds = ref(0)

let intervalId = null

const startTimer = () => {
  intervalId = setInterval(() => {
    if (minutes.value === 0 && seconds.value === 0) {
      clearInterval(intervalId)
      return
    }
    if (seconds.value === 0) {
      minutes.value--
      seconds.value = 59
    } else {
      seconds.value--
    }
  }, 1000)
}

const formattedTime = computed(() => {
  const formattedMinutes = minutes.value.toString().padStart(2, '0')
  const formattedSeconds = seconds.value.toString().padStart(2, '0')
  return `${formattedMinutes}:${formattedSeconds}`
})

onMounted(() => {
  startTimer()
})
template
<div>
      <div>残り時間</div>
      <div>{{ formattedTime }}</div>
</div>

文脈ごとに解説していきます。

const minutes = ref(6)
const seconds = ref(0)

minutesとsecondsと2つのリアクティブ変数を定義。ref(6)は初期値を6にしてタイマーを6分にします。

let intervalId = null

intervalIdという変数を定義して初期値をnullに。
後にsetIntervalId()の戻り値を割り当て、タイマーの戻り値を停止する。

const startTimer = () => {
  intervalId = setInterval(() => {
    if (minutes.value === 0 && seconds.value === 0) {
      clearInterval(intervalId)
      return
    }
    if (seconds.value === 0) {
      minutes.value--
      seconds.value = 59
    } else {
      seconds.value--
    }
  }, 1000)
}

カウントダウンの制御部分です。
startTimer関数を定義します。
intervalId = setInterval(() =>、setInterval()は指定された時間間隔ごとに指定された関数を実行するjavascript関数
アロー関数を使い中にタイマーロジックを実装。

if (minutes.value === 0 && seconds.value === 0)は
if文を使いminutes分が0かつsecondsが0になったとき、つまりタイマーが0分0秒になったとき、
clearInterval(intervalId)を使用してタイマーを停止します。
intervalIdをクリア。

if (seconds.value === 0) {
minutes.value--
seconds.value = 59
} else {
seconds.value--
}
はseconds(秒)が0かどうかを判断しています。0なら処理を実行。
minutes.valueを1減らす(5分00秒→4分59秒になる)。
seconds.value = 59は59にリセット(59秒になる)。
secondsが0でない場合はsecondsを1減らす(秒が1秒減る)。


}, 1000)
で1000ミリ秒(1秒)ごとに関数が実行される。

const formattedTime = computed(() => {
  const formattedMinutes = minutes.value.toString().padStart(2, '0')
  const formattedSeconds = seconds.value.toString().padStart(2, '0')
  return `${formattedMinutes}:${formattedSeconds}`
})

時間を分と秒で分けて表示します。
vue.js本体で用意されているcomputed()関数を利用してformattedTime計算プロパティを定義
ここではcomputed()関数は割愛しますが簡単に説明すると
ここでは計算結果をリアルタイムで表示してくれます。
computed()関数を使うためにimport { ref, computed } from 'vue'にします。

const formattedMinutes = minutes.value.toString().padStart(2, '0')
ではminutes(分)というリアクティブ変数が変更されるたびに自動計算される。
padStart(2, '0')は分を2桁の数字に変えています。
例えばコードを書かなければweb上の表示は05:59→5:59になる。
secondsも同様の処理を行います。
ruturnとして`${formattedMinutes}:${formattedSeconds}`web上の表示を2桁整数の分:秒で表示します。

onMounted(() => {
  startTimer()
})

コンポーネントがマウントされた後にstartTimerが実行。
忘れずにimport { ref, computed, onMounted } from 'vue'にして
onMountedをインポートしておきます。

以上で実装完了です。
そもそもvueでカウントダウンを実装する必要があったのかは疑問ですが、
今回私がオリジナルアプリケーションを作成する中で
時間制限を設けたかったので実装してみました。
私が使用した参考書も載せておきます。

過去1長く、悩んだ箇所ですが形になったのでよかったです。