Vue3日期选择器(DatePicker)

本组件基于 @vuepic/vue-datepicker 插件进行了二次封装,以便更适合日常使用!

官方文档:https://vue3datepicker.com/installation/

除了年、月、时分秒选择器以外,其余选择的日期(v-model:date)均已调整为返回时间戳!

可自定义设置以下二次封装属性(也可根据官方文档设定相应属性,组件已设置继承所有属性):

  • 日期选择器宽度(width),类型:number,默认 180px

  • 选择器模式(mode),类型:string,默认 'date',可选:时间time,日期date,周week,月month,年year

  • 是否增加时间选择(showTime),默认 false

  • 是否展示”今天“按钮(showToday),默认 false

  • 当前选中日期(v-model:date),类型:number | number[] | {month:number,year:number} | {hours:number,minutes:number,seconds:number},默认 0

常用官方属性举例(更多使用方式还请查阅官方文档,功能设计非常全面,各部分主题颜色也均可自定义修改!):

  • 日期展示格式(format),类型:string,默认 'yyyy-MM-dd',可选(y: 年, M: 月, d: 天, H: 时, m: 分, s: 秒)

  • 范围选择器是否使用双日期面板(multiCalendars),类型:boolean,默认 false

  • 定义选择顺序(flow),类型:array,默认 [],可选 ("calendar" | "time" | "month" | "year" | "minutes" | "hours" | "seconds")[]

  • 样式主题是否使用黑色(dark),类型:boolean,默认 false

  • 是否展示秒选择(enable-seconds),类型:boolean,默认 false

效果如下图:

①创建日期选择器组件DatePicker.vue:

<script setup lang="ts">
import VueDatePicker from '@vuepic/vue-datepicker'
import '@vuepic/vue-datepicker/dist/main.css'
import { ref, computed, watch } from 'vue'

interface Props {
  inheritAttrs?: boolean, // 默认值:true
  width?: number, // 日期选择器宽度
  mode?: string, // 选择器模式,可选:时间time,日期date,周week,月month,年year
  // format?: string, // 日期展示格式,(y: 年, M: 月, d: 天, H: 时, m: 分, s: 秒)
  showTime?: boolean, // 是否增加时间选择
  showToday?: boolean, // 是否展示”今天“按钮
  // multiCalendars?: boolean, // 范围选择器是否使用双日期面板
  // flow?: any[], // 定义选择顺序 ("calendar" | "time" | "month" | "year" | "minutes" | "hours" | "seconds")[]
  // dark?: boolean, // 样式主题是否使用黑色
  date?: number|number[]|{month:number,year:number}|{hours:number,minutes:number,seconds:number} // (v-model)当前选中日期
}
const props = withDefaults(defineProps<Props>(), {
  inheritAttrs: false,
  width: 180,
  mode: 'date',
  // format: 'yyyy-MM-dd',
  showTime: false,
  showToday: false,
  // multiCalendars: false,
  // flow: () => [],
  // dark: false,
  date: 0
})
const date = ref(props.date)
watch(date, (to) => {
  // console.log('s to:', to)
  emit('update:date', to)
})
const emit = defineEmits(['update:date'])
const modelType = computed(() => {
  if (['time', 'month', 'year'].includes(props.mode)) {
    return ''
  } else {
    return 'timestamp'
  }
})
const time = computed(() => {
  return props.mode === 'time'
})
const week = computed(() => {
  return props.mode === 'week'
})
const month = computed(() => {
  return props.mode === 'month'
})
const year = computed(() => {
  return props.mode === 'year'
})
// const format = (date: Date) => {
//   const day = date.getDate()
//   const month = date.getMonth() + 1
//   const year = date.getFullYear()
//   return `${year}-${month}-${day}`
// }
</script>
<template>
  <div class="m-datepicker" :style="`width: ${width}px;`">
    <VueDatePicker
      v-model="date"
      locale="zh-CN"
      :month-change-on-scroll="false"
      :enable-time-picker="showTime"
      :time-picker="time"
      :week-picker="week"
      :month-picker="month"
      :year-picker="year"
      :show-now-button="showToday"
      auto-apply
      text-input
      :model-type="modelType"
      :day-names="['一', '二', '三', '四', '五', '六', '七']"
      now-button-label="今天"
      v-bind="$attrs">
    </VueDatePicker>
  </div>
</template>
<style lang="less" scoped>
.m-datepicker {
  display: inline-block;
  box-sizing: border-box;
}
.dp__theme_dark { // dark theme
  --dp-background-color: #212121;
  --dp-text-color: #ffffff;
  --dp-hover-color: #484848;
  --dp-hover-text-color: #ffffff;
  --dp-hover-icon-color: #959595;
  --dp-primary-color: #005cb2;
  --dp-primary-text-color: #ffffff;
  --dp-secondary-color: #a9a9a9;
  --dp-border-color: #2d2d2d;
  --dp-menu-border-color: #2d2d2d;
  --dp-border-color-hover: #aaaeb7;
  --dp-disabled-color: #737373;
  --dp-scroll-bar-background: #212121;
  --dp-scroll-bar-color: #484848;
  --dp-success-color: #00701a;
  --dp-success-color-disabled: #428f59;
  --dp-icon-color: #959595;
  --dp-danger-color: #e53935;
  --dp-highlight-color: rgba(0, 92, 178, 0.2);
}
.dp__theme_light { // light theme
  --dp-background-color: #ffffff;
  --dp-text-color: #212121;
  --dp-hover-color: #f3f3f3;
  --dp-hover-text-color: #212121;
  --dp-hover-icon-color: #959595;
  --dp-primary-color: #1976d2;
  --dp-primary-text-color: #f8f5f5;
  --dp-secondary-color: #c0c4cc;
  --dp-border-color: #ddd;
  --dp-menu-border-color: #ddd;
  --dp-border-color-hover: #aaaeb7;
  --dp-disabled-color: #f6f6f6;
  --dp-scroll-bar-background: #f3f3f3;
  --dp-scroll-bar-color: #959595;
  --dp-success-color: #76d275;
  --dp-success-color-disabled: #a3d9b1;
  --dp-icon-color: #959595;
  --dp-danger-color: #ff6f60;
  --dp-highlight-color: rgba(25, 118, 210, 0.1);
}
</style>

②在要使用的页面引入:

<script setup lang="ts">
import { DatePicker } from './DatePicker.vue'
import { ref, watch } from 'vue'
import { endOfMonth, endOfYear, startOfMonth, startOfYear, subMonths } from 'date-fns'

const dateValue = ref(1678936740000)
const rangeValue = ref<number[]>([1678936740000, 1679541540000])
const timeRangeValue = ref([
  {
    hours: 10,
    minutes: 20,
    seconds: 30
  },
  {
    hours: 14,
    minutes: 20,
    seconds: 30
  }
])
const presetRanges = ref([
  { label: 'Today', range: [new Date(), new Date()] },
  { label: 'This month', range: [startOfMonth(new Date()), endOfMonth(new Date())] },
  {
    label: 'Last month',
    range: [startOfMonth(subMonths(new Date(), 1)), endOfMonth(subMonths(new Date(), 1))],
  },
  { label: 'This year', range: [startOfYear(new Date()), endOfYear(new Date())] }
])
const timeValue = ref({
  hours: 10,
  minutes: 20
})
const secondsValue = ref({
  hours: 10,
  minutes: 20,
  seconds: 30
})
const weekValue = ref([1678032000000, 1678636799999])
const monthValue = ref({
  year: 2023,
  month: 0
})
const yearValue = ref(2023)

watch(dateValue, (to) => {
  console.log('p to:', to)
})
watch(rangeValue, (to) => {
  console.log('p to:', to)
})
watch(timeValue, (to) => {
  console.log('p to:', to)
})
watch(weekValue, (to) => {
  console.log('p to:', to)
})
watch(monthValue, (to) => {
  console.log('p to:', to)
})
watch(yearValue, (to) => {
  console.log('p to:', to)
})
</script>
<template>
  <div>
    <h2 class="mb10">DatePicker 日期选择器基本使用</h2>
    <h2 class="mb10">日期选择器(mode: date 默认)</h2>
    <DatePicker
      placeholder="请选择日期"
      v-model:date="dateValue"
      mode="date"
      show-today
      format="yyyy-MM-dd"
      :width="180" />
    <h2 class="mt30 mb10">禁用过去的日期选择器(mode: date )</h2>
    <DatePicker
      placeholder="请选择日期"
      v-model:date="dateValue"
      mode="date"
      :min-date="new Date()"
      format="yyyy-MM-dd"
      :width="180" />
    <h2 class="mt30 mb10">禁用未来的日期选择器(mode: date )</h2>
    <DatePicker
      placeholder="请选择日期"
      v-model:date="dateValue"
      mode="date"
      :max-date="new Date()"
      format="yyyy-MM-dd"
      :width="180" />
    <h2 class="mt30 mb10">日期时间选择器(mode: date & show-time & enable-seconds)</h2>
    <DatePicker
      placeholder="请选择日期时间"
      v-model:date="dateValue"
      mode="date"
      format="yyyy-MM-dd HH:mm:ss"
      :width="240"
      show-time
      enable-seconds />
    <h2 class="mt30 mb10">日期范围选择器(range)</h2>
    <DatePicker
      placeholder="请选择日期范围"
      v-model:date="rangeValue"
      range
      :preset-ranges="presetRanges"
      format="yyyy-MM-dd"
      :width="280" />
    <h2 class="mt30 mb10">日期范围选择器,双日期面板(range & multi-calendars)</h2>
    <DatePicker
      placeholder="请选择日期范围"
      v-model:date="rangeValue"
      mode="range"
      format="yyyy-MM-dd"
      :width="280"
      range
      multi-calendars />
    <h2 class="mt30 mb10">时分选择器(mode: time & show-time)</h2>
    <DatePicker
      placeholder="请选择时间"
      v-model:date="timeValue"
      mode="time"
      show-time
      mode-height="120"
      format="HH:mm"
      :width="120" />
    <h2 class="mt30 mb10">时分秒选择器(mode: time & show-time & enable-seconds)</h2>
    <DatePicker
      placeholder="请选择时间"
      v-model:date="secondsValue"
      mode="time"
      show-time
      enable-seconds
      mode-height="120"
      format="HH:mm:ss"
      :width="150" />
    <h2 class="mt30 mb10">时分秒范围选择器(mode: time & range & show-time & enable-seconds)</h2>
    <DatePicker
      placeholder="请选择时间"
      v-model:date="timeRangeValue"
      mode="time"
      show-time
      range
      enable-seconds
      mode-height="120"
      format="HH:mm:ss"
      :width="240" />
    <h2 class="mt30 mb10">周选择器(mode: week)</h2>
    <DatePicker
      placeholder="请选择周"
      v-model:date="weekValue"
      mode="week"
      format="yyyy-MM-dd"
      :width="280" />
    <h2 class="mt30 mb10">月选择器(mode: month)</h2>
    <DatePicker
      placeholder="请选择月"
      v-model:date="monthValue"
      mode="month"
      format="yyyy-MM"
      :width="150" />
    <h2 class="mt30 mb10">年选择器(mode: year)</h2>
    <DatePicker
      placeholder="请选择年"
      v-model:date="yearValue"
      mode="year"
      format="yyyy"
      :width="120" />
  </div>
</template>
<style lang="less" scoped>
</style>

猜你喜欢

转载自blog.csdn.net/Dandrose/article/details/129954665