Skip to content

TimePicker 時間選択 - Vant 4

TimePicker 時間ピッカー ⏰

紹介

分・秒まで正確にコントロール!TimePicker は強力な時間選択コンポーネントで、時・分・秒の柔軟な選択に対応します。アラーム設定、予約時間、所要時間の記録など、滑らかで直感的な体験を提供します。✨

⏰ 時の魔法使い - すべての瞬間を正確に捉える!TimePicker は親切な時間管理人のように、望む時刻へ簡単に到達できます。通常はポップアップと組み合わせて、優雅な選択体験を提供します。

取り込み

以下の方法でコンポーネントをグローバル登録します。詳細はコンポーネント登録を参照してください。

js
import { createApp } from 'vue';
import { TimePicker } from 'vant';

const app = createApp();
app.use(TimePicker);

コード例

🎯 基本的な使い方 - 時間選択の第一歩

時計の針を回すように、滑らかな操作で目標の時刻へすばやく移動できます。

html
<template>
  <van-time-picker 
    v-model="currentTime" 
    title="時間を選択" 
    @confirm="onConfirm"
    @cancel="onCancel"
  />
</template>
js
import { ref } from 'vue';
import { showToast } from 'vant';

export default {
  setup() {
    const currentTime = ref(['12', '00']);
    
    const onConfirm = ({ selectedValues }) => {
      showToast(`選択した時間:${selectedValues.join(':')}`);
    };
    
    const onCancel = () => {
      showToast('選択をキャンセル');
    };
    
    return { 
      currentTime,
      onConfirm,
      onCancel
    };
  },
};

🎨 オプションタイプ - 自由な時間構成

時間は積み木のように自由に組み合わせ可能です。columns-typehour(時)・minute(分)・second(秒)を任意順で構成できます。

比如:

  • ['hour'] を渡して時のみ選択
  • ['minute'] を渡して分のみ選択
  • ['minute', 'second'] で分と秒を選択
  • ['hour', 'minute', 'second'] で時・分・秒を選択
html
<!-- 時・分を選択 - 日常的な設定に適する -->
<van-time-picker
  v-model="currentTime"
  title="時間を選択"
  :columns-type="['hour', 'minute']"
  @confirm="onTimeConfirm"
/>

<!-- 時・分・秒を選択 - 秒単位で精密制御 -->
<van-time-picker
  v-model="preciseTime"
  title="精密な時間"
  :columns-type="['hour', 'minute', 'second']"
  @confirm="onPreciseTimeConfirm"
/>

<!-- 分・秒を選択 - カウントダウンやタイマーに適する -->
<van-time-picker
  v-model="durationTime"
  title="所要時間を設定"
  :columns-type="['minute', 'second']"
  @confirm="onDurationConfirm"
/>
js
import { ref } from 'vue';

export default {
  setup() {
    const currentTime = ref(['12', '00']);
    const preciseTime = ref(['12', '00', '00']);
    const durationTime = ref(['05', '30']);
    
    const onTimeConfirm = ({ selectedValues }) => {
      console.log('選択した時間:', selectedValues.join(':'));
    };
    
    const onPreciseTimeConfirm = ({ selectedValues }) => {
      console.log('精密な時間:', selectedValues.join(':'));
    };
    
    const onDurationConfirm = ({ selectedValues }) => {
      console.log('所要時間の設定:', `${selectedValues[0]}分${selectedValues[1]}秒`);
    };
    
    return {
      currentTime,
      preciseTime,
      durationTime,
      onTimeConfirm,
      onPreciseTimeConfirm,
      onDurationConfirm
    };
  }
};

🚧 時間範囲 - 境界の設定

min-hourmax-hour などの属性で、時・分・秒の選択範囲を制限し、より正確で秩序ある選択を実現します。

以下の例では、時は 10 ~ 20、分は 30 ~ 40 の範囲で選択できます。

html
<template>
  <!-- 時と分の範囲を制限 -->
  <van-time-picker
    v-model="currentTime"
    title="時間を選択"
    :min-hour="10"
    :max-hour="20"
    :min-minute="30"
    :max-minute="40"
    @confirm="onConfirm"
  />
  
  <!-- ランチ時間ピッカー (11:30-14:00) -->
  <van-time-picker
    v-model="lunchTime"
    title="ランチ時間を選択"
    :min-hour="11"
    :max-hour="14"
    :min-minute="30"
    @confirm="onLunchTimeConfirm"
  />
</template>
js
import { ref } from 'vue';
import { showToast } from 'vant';

export default {
  setup() {
    const currentTime = ref(['12', '35']);
    const lunchTime = ref(['12', '30']);
    
    const onConfirm = ({ selectedValues }) => {
      showToast(`選択した時間:${selectedValues.join(':')}`);
    };
    
    const onLunchTimeConfirm = ({ selectedValues }) => {
      showToast(`ランチ時間:${selectedValues.join(':')}`);
    };
    
    return { 
      currentTime,
      lunchTime,
      onConfirm,
      onLunchTimeConfirm
    };
  },
};

### 🌍 全体の時間範囲 - 全体制御

`min-time``max-time` を使って全体の時間範囲を制限します。`10:00:00` のようなフォーマットを使用します。

-   `min-time` を設定すると、`min-hour``min-minute``min-second` は無効になります。
-   `max-time` を設定すると、`max-hour``max-minute``max-second` は無効になります。

以下の例では、`09:40:10` から `20:20:50` の任意時間を選択できます。

```html
js
import { ref } from'vue'; exportdefault { setup() { const currentTime = ref(['12', '00', '00']); return { currentTime }; }, };

✨ フォーマットオプション - 時間テキストの装飾

formatter 関数で表示テキストを美しく整形できます。各時間単位をわかりやすく装飾します。

html
<template>
  <!-- 中国語の時間フォーマット -->
  <van-time-picker
    v-model="chineseTime"
    title="時間を選択"
    :formatter="chineseFormatter"
    @confirm="onChineseTimeConfirm"
  />
  
  <!-- 12時間制フォーマット -->
  <van-time-picker
    v-model="ampmTime"
    title="時間を選択"
    :formatter="ampmFormatter"
    @confirm="onAmpmTimeConfirm"
  />
</template>
js
import { ref } from 'vue';
import { showToast } from 'vant';

export default {
  setup() {
    const chineseTime = ref(['12', '00']);
    const ampmTime = ref(['12', '00']);

    // 中国語フォーマッタ
    const chineseFormatter = (type, option) => {
      if (type === 'hour') {
        option.text += '时';
      }
      if (type === 'minute') {
        option.text += '分';
      }
      if (type === 'second') {
        option.text += '秒';
      }
      return option;
    };
    
    // 12小时制格式化器
    const ampmFormatter = (type, option) => {
      if (type === 'hour') {
        const hour = parseInt(option.value);
        if (hour === 0) {
          option.text = '12 AM';
        } else if (hour < 12) {
          option.text = `${hour} AM`;
        } else if (hour === 12) {
          option.text = '12 PM';
        } else {
          option.text = `${hour - 12} PM`;
        }
      }
      if (type === 'minute') {
        option.text += ' min';
      }
      return option;
    };

    const onChineseTimeConfirm = ({ selectedValues }) => {
      showToast(`中国語時間:${selectedValues[0]}時${selectedValues[1]}分`);
    };
    
    const onAmpmTimeConfirm = ({ selectedValues }) => {
      showToast(`12時間制:${selectedValues.join(':')}`);
    };

    return {
      chineseTime,
      ampmTime,
      chineseFormatter,
      ampmFormatter,
      onChineseTimeConfirm,
      onAmpmTimeConfirm
    };
  },
};

🔍 フィルタリングオプション - 時間の精密選別

filter 関数でオプション配列を精密にフィルタリングできます。不要な時間を除外し、任意の時間間隔を実現します。

html
<template>
  <!-- 5 分間隔の選択器 -->
  <van-time-picker
    v-model="intervalTime"
    title="時間を選択(5 分間隔)"
    :filter="intervalFilter"
    @confirm="onIntervalTimeConfirm"
  />
  
  <!-- 勤務時間フィルタ -->
  <van-time-picker
    v-model="workTime"
    title="勤務時間を選択"
    :filter="workTimeFilter"
    @confirm="onWorkTimeConfirm"
  />
</template>
js
import { ref } from 'vue';
import { showToast } from 'vant';

export default {
  setup() {
    const intervalTime = ref(['12', '00']);
    const workTime = ref(['09', '00']);

    // 5 分間隔フィルタ
    const intervalFilter = (type, options) => {
      if (type === 'minute') {
        return options.filter((option) => Number(option.value) % 5 === 0);
      }
      return options;
    };
    
    // 勤務時間フィルタ
    const workTimeFilter = (type, options) => {
      if (type === 'hour') {
        // 勤務時間 9:00-18:00 のみ表示
        return options.filter((option) => {
          const hour = Number(option.value);
          return hour >= 9 && hour <= 18;
        });
      }
      if (type === 'minute') {
        // 00分と30分のみ表示
        return options.filter((option) => {
          const minute = Number(option.value);
          return minute === 0 || minute === 30;
        });
      }
      return options;
    };

    const onIntervalTimeConfirm = ({ selectedValues }) => {
      showToast(`間隔時間:${selectedValues.join(':')}`);
    };
    
    const onWorkTimeConfirm = ({ selectedValues }) => {
      showToast(`勤務時間:${selectedValues.join(':')}`);
    };

    return {
      intervalTime,
      workTime,
      intervalFilter,
      workTimeFilter,
      onIntervalTimeConfirm,
      onWorkTimeConfirm
    };
  },
};

🚀 上級用法 - 時間フィルタの極意

filter の第 3 引数で現在の選択状態を取得できます。非制御モードでも柔軟で賢いフィルタリングが可能です。

html
js
exportdefault { setup() { constfilter = (type, options, values) => { const hour = +values[0]; if (type === 'hour') { return options.filter( (option) =>Number(option.value) >= 8 && Number(option.value) <= 18, ); } if (type === 'minute') { options = options.filter((option) =>Number(option.value) % 10 === 0); if (hour === 8) { return options.filter((option) =>Number(option.value) >= 40); } if (hour === 18) { return options.filter((option) =>Number(option.value) <= 20); } } return options; }; return { filter, }; }, };

API

Props

パラメータ説明デフォルト
v-model🎯 現在選択されている時間(配列形式)string[]-
columns-type⚙️ 選択項目の種類(hourminutesecond の配列)string[]['hour', 'minute']
min-hour🌅 選択可能な最小の時number | string0
max-hour🌇 選択可能な最大の時number | string23
min-minute⏰ 選択可能な最小の分number | string0
max-minute⏰ 選択可能な最大の分number | string59
min-second⏱️ 選択可能な最小の秒number | string0
max-second⏱️ 選択可能な最大の秒number | string59
min-time v4.5.0🚫 選択可能な最小時刻(例 07:40:00)。使用時は min-hour min-minute min-second は無効string-
max-time v4.5.0🚫 選択可能な最大時刻(例 10:20:00)。使用時は max-hour max-minute max-second は無効string-
title📝 ヘッダーのタイトルstring''
confirm-button-text✅ 確認ボタンの文言string确认
cancel-button-text❌ キャンセルボタンの文言string取消
show-toolbar🔧 ヘッダー(ツールバー)を表示booleantrue
loading⏳ ローディング状態を表示(非同期データ時)booleanfalse
readonly🔒 読み取り専用(選択不可)booleanfalse
filter🔍 オプションのフィルタ関数(type: string, options: PickerOption[], values: string[]) => PickerOption[]-
formatter🎨 オプションのフォーマット関数(type: string, option: PickerOption) => PickerOption-
option-height📏 オプション高さ(px vw vh rem をサポート、デフォルト pxnumber | string44
visible-option-num👁️ 表示されるオプション数number | string6
swipe-duration🏃 慣性スクロール時間(msnumber | string1000

Events

イベント名説明コールバック引数
confirm✅ 完了ボタンで発火。時間を確定{ selectedValues, selectedOptions, selectedIndexes }
cancel❌ キャンセルボタンで発火。選択を取り消し{ selectedValues, selectedOptions, selectedIndexes }
change🔄 オプション変更時に発火。操作をリアルタイムに反映{ selectedValues, selectedOptions, selectedIndexes, columnIndex }

Slots

名前説明引数
toolbar🔧 ヘッダー全体のカスタマイズ-
title📝 タイトルのカスタマイズ-
confirm✅ 確認ボタンのカスタマイズ-
cancel❌ キャンセルボタンのカスタマイズ-
option🎨 オプション表示のカスタマイズoption: PickerOption, index: number
columns-top⬆️ オプション上部のカスタマイズ-
columns-bottom⬇️ オプション下部のカスタマイズ-

メソッド

ref で Picker インスタンスを取得してメソッドを呼び出せます。詳細はコンポーネントインスタンスメソッドを参照してください。

メソッド名説明引数戻り値
confirm✅ 慣性スクロールを停止し confirm を発火--
getSelectedTime🎯 現在選択中の時間を取得-string[]

型定義 📝

TypeScript の型定義を提供します:

ts
import type { TimePickerProps, TimePickerColumnType } from 'vant';

TimePickerInstance はコンポーネントインスタンスの型です:

ts
import { ref } from 'vue';
import type { TimePickerInstance } from 'vant';

const timePickerRef = ref<TimePickerInstance>();

// プログラムで確認
timePickerRef.value?.confirm();

// 現在選択中の時間を取得
const selectedTime = timePickerRef.value?.getSelectedTime();

よくある質問

デスクトップで操作できない?

デスクトップ適応 を参照してください。

🎯 ベストプラクティス

時間ピッカーとポップアップの組み合わせ

html
<template>
  <van-cell title="時間を選択" :value="timeText" @click="showPicker = true" />
  <van-popup v-model:show="showPicker" position="bottom">
    <van-time-picker
      v-model="currentTime"
      title="時間を選択"
      @confirm="onConfirm"
      @cancel="showPicker = false"
    />
  </van-popup>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  setup() {
    const showPicker = ref(false);
    const currentTime = ref(['12', '00']);
    
    const timeText = computed(() => {
      return currentTime.value.join(':');
    });
    
    const onConfirm = ({ selectedValues }) => {
      currentTime.value = selectedValues;
      showPicker.value = false;
    };
    
    return {
      showPicker,
      currentTime,
      timeText,
      onConfirm
    };
  }
};
</script>

レスポンシブな時間範囲設定

javascript
// 現在時刻に基づき選択可能範囲を動的設定
const getCurrentTimeRange = () => {
  const now = new Date();
  const currentHour = now.getHours();
  const currentMinute = now.getMinutes();
  
  return {
    minHour: currentHour,
    minMinute: currentHour === now.getHours() ? currentMinute : 0,
    maxHour: 23,
    maxMinute: 59
  };
};

スマートなデフォルト値設定

javascript
// 妥当なデフォルト時間を設定
const getDefaultTime = () => {
  const now = new Date();
  const hour = now.getHours().toString().padStart(2, '0');
  const minute = Math.ceil(now.getMinutes() / 15) * 15; // 15 分に切り上げ
  return [hour, minute.toString().padStart(2, '0')];
};

💡 使い方のコツ

多言語の時間フォーマット

javascript
const createTimeFormatter = (locale = 'zh-CN') => {
  const formatMap = {
    'zh-CN': { hour: '时', minute: '分', second: '秒' },
    'en-US': { hour: 'h', minute: 'm', second: 's' },
    'ja-JP': { hour: '時', minute: '分', second: '秒' }
  };
  
  return (type, option) => {
    const suffix = formatMap[locale][type] || '';
    option.text += suffix;
    return option;
  };
};

上級フィルタ機能

javascript
// 工作时间过滤器
const workTimeFilter = (type, options, values) => {
  if (type === 'hour') {
    return options.filter(option => {
      const hour = Number(option.value);
      return hour >= 9 && hour <= 18; // 只显示工作时间
    });
  }
  
  if (type === 'minute') {
    return options.filter(option => {
      const minute = Number(option.value);
      return minute % 15 === 0; // 只显示15分钟间隔
    });
  }
  
  return options;
};

列タイプの動的切り替え

html
<template>
  <van-radio-group v-model="timeMode" direction="horizontal">
    <van-radio name="hour">時のみ</van-radio>
    <van-radio name="minute">時・分</van-radio>
    <van-radio name="second">秒まで</van-radio>
  </van-radio-group>
  
  <van-time-picker
    v-model="currentTime"
    :columns-type="columnsType"
  />
</template>

<script>
const timeMode = ref('minute');
const columnsType = computed(() => {
  const modeMap = {
    hour: ['hour'],
    minute: ['hour', 'minute'],
    second: ['hour', 'minute', 'second']
  };
  return modeMap[timeMode.value];
});
</script>

🔧 よくある問題の解決

時間フォーマットの互換性

javascript
// 異なる時間フォーマットに対応
const formatTimeValue = (timeArray) => {
  return timeArray.map(time => {
    // 2 桁に整形
    return time.toString().padStart(2, '0');
  });
};

// 時間文字列の解析
const parseTimeString = (timeString) => {
  const parts = timeString.split(':');
  return parts.map(part => part.padStart(2, '0'));
};

性能优化

javascript
// debounce で頻繁な change を最適化
import { debounce } from 'lodash-es';

const debouncedChange = debounce((selectedValues) => {
  console.log('時間選択の変化:', selectedValues);
  // 関連ロジックを実行
}, 300);

データ検証とエラー処理

javascript
// 時間の妥当性検証
const validateTime = (timeArray) => {
  const [hour, minute, second] = timeArray.map(Number);
  
  if (hour < 0 || hour > 23) return false;
  if (minute < 0 || minute > 59) return false;
  if (second !== undefined && (second < 0 || second > 59)) return false;
  
  return true;
};

// エラー処理
const handleTimeError = (error) => {
  console.error('時間ピッカーエラー:', error);
  // デフォルト時間にリセット
  currentTime.value = ['12', '00'];
};

🎨 デザインのヒント

テーマ化時間ピッカー

css
/* ダークテーマ */
.van-time-picker--dark {
  --van-picker-background: #1a1a1a;
  --van-picker-option-text-color: #ffffff;
  --van-picker-option-selected-text-color: #1989fa;
}

/* グラデーション背景 */
.van-time-picker--gradient {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

/* 角丸スタイル */
.van-time-picker--rounded {
  border-radius: 20px;
  overflow: hidden;
}

アニメーション強化

css
/* オプション切り替えアニメーション */
.van-picker-column__item {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.van-picker-column__item--selected {
  transform: scale(1.1);
  font-weight: bold;
  color: #1989fa;
}

/* ポップアップアニメーション */
.time-picker-enter-active,
.time-picker-leave-active {
  transition: all 0.3s ease;
}

.time-picker-enter-from,
.time-picker-leave-to {
  opacity: 0;
  transform: translateY(100%);
}

クリエイティブなインタラクション

javascript
// バイブレーションフィードバック
const handleTimeChange = () => {
  if ('vibrate' in navigator) {
    navigator.vibrate(50); // 軽い振動のフィードバック
  }
};

// サウンドフィードバック
const playTickSound = () => {
  const audio = new Audio('/sounds/tick.mp3');
  audio.volume = 0.3;
  audio.play().catch(() => {
    // 音声再生失敗を黙って処理
  });
};

🚀 上級機能の拡張

スマート時間推薦システム

javascript
// ユーザー履歴選択に基づく推薦
class TimeRecommendationSystem {
  constructor() {
    this.history = JSON.parse(localStorage.getItem('timeHistory') || '[]');
  }
  
  // ユーザー選択を記録
  recordSelection(timeArray) {
    this.history.push({
      time: timeArray,
      timestamp: Date.now()
    });
    
    // 最近 50 件のみ保持
    if (this.history.length > 50) {
      this.history = this.history.slice(-50);
    }
    
    localStorage.setItem('timeHistory', JSON.stringify(this.history));
  }
  
  // 推奨時間を取得
  getRecommendations() {
    const timeFrequency = {};
    
    this.history.forEach(record => {
      const timeKey = record.time.join(':');
      timeFrequency[timeKey] = (timeFrequency[timeKey] || 0) + 1;
    });
    
    return Object.entries(timeFrequency)
      .sort(([,a], [,b]) => b - a)
      .slice(0, 3)
      .map(([time]) => time.split(':'));
  }
}

多タイムゾーン時間ピッカー

javascript
// 複数タイムゾーン対応
const createTimezoneTimePicker = (timezone = 'Asia/Shanghai') => {
  const getTimezoneTime = () => {
    const now = new Date();
    const utc = now.getTime() + (now.getTimezoneOffset() * 60000);
    const targetTime = new Date(utc + (getTimezoneOffset(timezone) * 60000));
    
    return [
      targetTime.getHours().toString().padStart(2, '0'),
      targetTime.getMinutes().toString().padStart(2, '0')
    ];
  };
  
  const getTimezoneOffset = (tz) => {
    // タイムゾーンのオフセットマップ
    const timezones = {
      'Asia/Shanghai': 8,
      'America/New_York': -5,
      'Europe/London': 0,
      'Asia/Tokyo': 9
    };
    return (timezones[tz] || 0) * 3600000;
  };
  
  return {
    getTimezoneTime,
    formatTimezone: (time) => {
      return `${time.join(':')} (${timezone})`;
    }
  };
};

📚 参考資料

技術ドキュメント

デザインガイド

ユーザー体験

関連ドキュメント 📚

🎯 コアコンポーネント

🔧 補助コンポーネント

⚡ 上級機能

Vant に基づく企業向けモバイルソリューション