Skip to content

CountDown 倒數計時 - Vant 4

⏰ CountDown 倒數計時

⏳ 介紹

時間就像流水一樣珍貴,CountDown 倒數計時元件就是你的專屬時間管家!⏰ 它能夠精確到毫秒地展示倒數計時,就像一個永不疲倦的時間守護者。

無論是激動人心的活動倒數計時 🎉、緊張刺激的驗證碼倒數計時 📱,還是各種需要時間提醒的場景,CountDown 都能像一位貼心的助手一樣,為你精準計時,讓每一秒都充滿儀式感!

📦 引入

透過以下方式來全域註冊元件,更多註冊方式請參考元件註冊

js
import { createApp } from'vue'; 
import { CountDown } from'vant'; 
const app = createApp(); 
app.use(CountDown);

🎯 程式碼演示

🔧 基礎用法 - 開啟你的時間之旅

就像設定一個鬧鐘一樣簡單!透過 time 屬性設定倒數計時的總時長(單位為毫秒),CountDown 就會像一個精準的時鐘一樣開始為你倒數每一秒。

html
js
import { ref } from'vue'; 
export default { 
  setup() { 
    const time = ref(30 * 60 * 60 * 1000); 
    return { time }; 
  }, 
};

🎨 自訂格式 - 讓時間穿上漂亮的外衣

時間也需要美美的展示方式!透過 format 屬性,你可以像設計師一樣為倒數計時定製專屬的顯示格式,讓時間以最優雅的姿態呈現在使用者面前。

html

⚡ 毫秒級渲染 - 追求極致的時間精度

想要更加絲滑的倒數計時體驗嗎?預設情況下,倒數計時每秒更新一次,就像心跳一樣穩定。但當你開啟 millisecond 屬性後,它就會變身為一台高精度的計時器,每毫秒都在跳動,給使用者帶來極致流暢的視覺體驗!

html

🎭 自訂樣式 - 釋放你的創意天賦

不滿足於預設的樣式?沒問題!透過插槽功能,你可以像藝術家一樣自由創作,打造獨一無二的倒數計時介面。timeData 物件就像你的調色盤,包含了所有時間資料,讓你的創意盡情揮灑!

html

🎮 手動控制 - 成為時間的主宰者

想要完全掌控時間的節奏?透過 ref 獲取元件實例,你就擁有了時間魔法的三大法術:start(開始)、pause(暫停)、reset(重置)。就像遙控器一樣,讓時間在你的指尖起舞!

html
js
import { showToast } from'vant'; 
export default { 
  setup() { 
    const countDown = ref(null); 
    const start = () => { countDown.value.start(); }; 
    const pause = () => { countDown.value.pause(); }; 
    const reset = () => { countDown.value.reset(); }; 
    const onFinish = () => showToast('倒數計時結束'); 
    return { start, pause, reset, onFinish, countDown, }; 
  }, 
};

API

Props

參數說明類型預設值
time倒數計時時長,單位毫秒*numberstring*
format時間格式stringHH:mm:ss
auto-start是否自動開始倒數計時booleantrue
millisecond是否開啟毫秒級渲染booleanfalse

format 格式

格式說明
DD天數
HH小時
mm分鐘
ss秒數
S毫秒(1 位)
SS毫秒(2 位)
SSS毫秒(3 位)

Events

事件名說明回調參數
finish倒數計時結束時觸發-
change倒數計時變化時觸發currentTime: CurrentTime

Slots

名稱說明參數
default自訂內容currentTime: CurrentTime

CurrentTime 格式

名稱說明類型
total剩餘總時間(單位毫秒)number
days剩餘天數number
hours剩餘小時number
minutes剩餘分鐘number
seconds剩餘秒數number
milliseconds剩餘毫秒number

方法

透過 ref 可以獲取到 CountDown 實例並呼叫實例方法,詳見元件實例方法

方法名說明參數返回值
start開始倒數計時--
pause暫停倒數計時--
reset重設倒數計時,若 auto-starttrue,重設後會自動開始倒數計時--

類型定義

元件匯出以下類型定義:

ts
import type { CountDownProps, CountDownInstance, CountDownCurrentTime, } from'vant';

CountDownInstance 是元件實例的類型,用法如下:

ts
import { ref } from'vue'; 
import type { CountDownInstance } from'vant'; 
const countDownRef = ref<CountDownInstance>(); 
countDownRef.value?.start();

主題定製

樣式變數

元件提供了下列 CSS 變數,可用於自訂樣式,使用方法請參考 ConfigProvider 元件

名稱預設值描述
--van-count-down-text-colorvar(--van-text-color)-
--van-count-down-font-sizevar(--van-font-size-md)-
--van-count-down-line-heightvar(--van-line-height-md)-

❓ 常見問題

在 iOS 系統上倒數計時不生效?

如果你遇到了在 iOS 上倒數計時不生效的問題,請確認在建立 Date 物件時沒有使用new Date('2020-01-01')這樣的寫法,iOS 不支援以中劃線分隔的日期格式,正確寫法是new Date('2020/01/01')

對此問題的詳細解釋:stackoverflow

🌟 最佳實踐

效能最佳化建議

javascript
// 避免頻繁的毫秒級渲染,除非必要
<van-count-down 
  :time="time" 
  :millisecond="false"  // 預設即可,效能更好
  format="HH:mm:ss" 
/>

// 大量倒數計時元件時,使用節流
import { throttle } from 'lodash-es';

const handleChange = throttle((currentTime) => {
  console.log('倒數計時變化:', currentTime);
}, 100);

使用者體驗最佳化

javascript
// 新增音效提醒
const onFinish = () => {
  // 播放提示音
  const audio = new Audio('/sounds/countdown-finish.mp3');
  audio.play();
  
  // 震動回饋(行動端)
  if (navigator.vibrate) {
    navigator.vibrate([200, 100, 200]);
  }
};

// 視覺回饋
const getCountdownClass = (seconds) => {
  if (seconds <= 10) return 'countdown-urgent';
  if (seconds <= 30) return 'countdown-warning';
  return 'countdown-normal';
};

💡 使用技巧

動態倒數計時場景

javascript
// 伺服器時間同步
const syncServerTime = async () => {
  const response = await fetch('/api/server-time');
  const serverTime = await response.json();
  const localTime = Date.now();
  const timeDiff = serverTime - localTime;
  
  // 調整倒數計時
  const adjustedTime = targetTime - timeDiff;
  return Math.max(0, adjustedTime);
};

// 網路斷線重連後同步
window.addEventListener('online', () => {
  syncServerTime().then(time => {
    countDownRef.value?.reset();
    // 重新設定時間
  });
});

多語言時間格式

javascript
const formatByLocale = (locale) => {
  const formats = {
    'zh-CN': 'DD天 HH:mm:ss',
    'en-US': 'DD days HH:mm:ss',
    'ja-JP': 'DD日 HH:mm:ss'
  };
  return formats[locale] || formats['zh-CN'];
};

🔧 常見問題解決

時間精度問題

javascript
// Q: 為什麼倒數計時不準確?
// A: 避免使用不準確的時間計算

// ❌ 錯誤做法
const endTime = new Date('2024-12-31 23:59:59');
const now = new Date();
const time = endTime - now; // 可能不準確

// ✅ 正確做法
const getAccurateTime = async () => {
  const response = await fetch('/api/server-time');
  const serverTime = await response.json();
  const endTime = new Date('2024-12-31T23:59:59Z').getTime();
  return Math.max(0, endTime - serverTime);
};

頁面切換後倒數計時停止

javascript
// 使用 Page Visibility API 處理頁面切換
let pausedTime = 0;

document.addEventListener('visibilitychange', () => {
  if (document.hidden) {
    // 頁面隱藏時記錄時間
    pausedTime = Date.now();
  } else {
    // 頁面顯示時同步時間
    if (pausedTime) {
      const elapsed = Date.now() - pausedTime;
      // 調整倒數計時
      syncCountdown(elapsed);
    }
  }
});

記憶體洩漏預防

javascript
// 元件銷毀時清理定時器
onUnmounted(() => {
  if (countDownRef.value) {
    countDownRef.value.pause();
  }
});

🎨 設計靈感

創意倒數計時樣式

css
/* 霓虹燈效果 */
.neon-countdown {
  color: #00ffff;
  text-shadow: 
    0 0 5px #00ffff,
    0 0 10px #00ffff,
    0 0 15px #00ffff;
  animation: neon-flicker 2s infinite alternate;
}

/* 翻頁效果 */
.flip-countdown {
  perspective: 1000px;
}

.flip-countdown .digit {
  transform-style: preserve-3d;
  transition: transform 0.6s;
}

/* 進度環形倒數計時 */
.circular-countdown {
  position: relative;
  width: 120px;
  height: 120px;
}

.circular-countdown svg {
  transform: rotate(-90deg);
}

.circular-countdown .progress-ring {
  stroke-dasharray: 377; /* 2 * π * 60 */
  stroke-dashoffset: 377;
  animation: countdown-progress linear;
}

主題變體

javascript
// 緊急倒數計時主題
const urgentTheme = {
  '--van-count-down-text-color': '#ff4444',
  '--van-count-down-font-size': '24px',
  '--van-count-down-font-weight': 'bold'
};

// 優雅倒數計時主題
const elegantTheme = {
  '--van-count-down-text-color': '#666',
  '--van-count-down-font-size': '16px',
  '--van-count-down-font-family': 'serif'
};

🚀 高級功能擴展

自訂倒數計時元件

vue
<template>
  <div class="advanced-countdown">
    <van-count-down
      ref="countDown"
      :time="time"
      :format="format"
      @change="handleChange"
      @finish="handleFinish"
    >
      <template #default="{ currentTime }">
        <div class="time-blocks">
          <div class="time-block">
            <span class="number">{{ currentTime.days }}</span>
            <span class="label">天</span>
          </div>
          <div class="time-block">
            <span class="number">{{ currentTime.hours }}</span>
            <span class="label">時</span>
          </div>
          <div class="time-block">
            <span class="number">{{ currentTime.minutes }}</span>
            <span class="label">分</span>
          </div>
          <div class="time-block">
            <span class="number">{{ currentTime.seconds }}</span>
            <span class="label">秒</span>
          </div>
        </div>
      </template>
    </van-count-down>
  </div>
</template>

📚 延伸閱讀

技術文件

設計資源

相關元件

基於Vant構建的企業級移動端解決方案