vue3 ts 写一个滑动选择的日期选择器组件

发布于:2025-05-10 ⋅ 阅读:(17) ⋅ 点赞:(0)

vue3 ts 写一个滑动选择的日期选择器组件

在这里插入图片描述

DatePicker.vue

<template>
  <div class="date-picker-container">
    <div class="date-picker">
      <select v-model="selectedYear" @change="updateDays">
        <option value="">Year</option>
        <option v-for="year in years" :key="year" :value="year">{{ year }}</option>
      </select>
      -
      <select v-model="selectedMonth" @change="updateDays">
        <option value="">Month</option>
        <option v-for="month in months" :key="month" :value="month">
          {{ String(month).padStart(2, "0") }}
        </option>
        -
      </select>
      -
      <select v-model="selectedDay">
        <option value="">Day</option>
        <option v-for="day in days" :key="day" :value="day">
          {{ String(day).padStart(2, "0") }}
        </option>
      </select>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, computed, watch, onMounted } from "vue";

const props = defineProps({
  modelValue: {
    type: String,
    default: "",
  },
});

const emit = defineEmits(["update:modelValue"]);

const years = ref<number[]>([]);
const months = ref<number[]>([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
const days = ref<number[]>([]);

const selectedYear = ref<string>("");
const selectedMonth = ref<string>("");
const selectedDay = ref<string>("");

const currentYear = new Date().getFullYear();
years.value = Array.from({ length: 150 }, (_, i) => currentYear - 100 + i);

const updateDays = () => {
  if (!selectedYear.value || !selectedMonth.value) {
    days.value = [];
    return;
  }
  const year = parseInt(selectedYear.value, 10);
  const month = parseInt(selectedMonth.value, 10);
  const daysInMonth = new Date(year, month, 0).getDate();
  days.value = Array.from({ length: daysInMonth }, (_, i) => i + 1);
};

const selectedDate = computed(() => {
  if (selectedYear.value && selectedMonth.value && selectedDay.value) {
    return `${selectedYear.value}-${String(selectedMonth.value).padStart(
      2,
      "0"
    )}-${String(selectedDay.value).padStart(2, "0")}`;
  }
  return "";
});

// 初始化值
onMounted(() => {});
// 改进的初始化函数
const initFromDateString = (dateStr: string) => {
  if (!dateStr) return;
  // 尝试解析各种可能的日期格式
  const parts = dateStr.split("-");
  if (parts.length === 3) {
    selectedYear.value = parts[0];
    // 检查 parts[1] 是否以 '0' 开头
    if (parts[1].startsWith("0")) {
      // 转换为数字
      selectedMonth.value = Number(parts[1]).toString(); // 或 +parts[1] 或 Number(parts[1])
    } else {
      // 如果不以 '0' 开头,保持原样或进行其他处理
      selectedMonth.value = parts[1];
    }
    if (parts[2].startsWith("0")) {
      // 转换为数字
      selectedDay.value = Number(parts[2]).toString(); // 或 +parts[1] 或 Number(parts[1])
    } else {
      // 如果不以 '0' 开头,保持原样或进行其他处理
      selectedDay.value = parts[2];
    }
  }
  updateDays();
};
// 监听 modelValue 变化
watch(
  () => props.modelValue,
  (newVal) => {
    initFromDateString(newVal);
  },
  { immediate: true }
);
// 监听选择的变化
watch(
  [selectedYear, selectedMonth, selectedDay],
  () => {
    const dateStr = selectedDate.value;
    emit("update:modelValue", dateStr);
  },
  { immediate: true }
);
</script>

<style scoped>
.date-picker-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
}
.date-picker {
  display: flex;
  gap: 10px;
}
select {
  width: 33%;
  padding: 5px;
  font-size: 16px;
  border-radius: 5px;
  border: 1px solid #dcdfe6;
  background-color: #fff;
  color: #606266;
}
</style>

在需要的地方引入

<template>
	<DatePicker v-model="ruleForm.Dateofbirth" />
<template>
...
<script lang="ts" setup name="FormInfo">
	import DatePicker from "./DatePicker.vue";
</script>

网站公告

今日签到

点亮在社区的每一天
去签到