VR视角 Vue3已毕一个纰漏的日期组件

发布日期:2024-09-30 21:31    点击次数:180

VR视角 Vue3已毕一个纰漏的日期组件

日期组件 需求 需要展示一个约略的日期,撑执切换展示的年份、月份,撑执切换选中日期 罕见日期展示小红点,比如若是当日有日程,不错用小红点标注 恶果展示

图片VR视角

青柠视频在线观看BD 念念路 表头: 上一年、上一月、面前月份展示、下一月、下一年 表体: 7列:["日", "一", "二", "三", "四", "五", "六"] 6行:一共必须包含本月扫数日期,会有两种情况:(1)5行能展示完好意思(2)6行能展示完好意思,兼容两种情况聘请不管什么情况王人展示6行 想明晰以上,念念路就特别清亮了,咱们只需要找到表格中的第一个日期,然后42个格子每个格子挨次往后推一天就不错了
ini 代码解读复制代码import dayjs from "dayjs";
const getDateList = () => {
  const firstDay = showDate.value.dayjs.startOf("month").startOf("week");
  const rows = 6;
  return Array(rows * 7)
    .fill(0)
    .map((n, i) => {
      const day = firstDay.add(i, "day");
      return getCalendarDate(day);
    });
};
选中的日期:咱们需要有一个值来记载选中的日期,纰漏高亮展示也纰漏后头切换时把柄选中的日期展示面前月份,是以界说了一个对象,默许是选中面前日期
ini 代码解读复制代码const getCalendarDate = (dayjs) => {
  return {
    year: dayjs.year(),
    month: dayjs.month(),
    date: dayjs.date(),
    value: dayjs.format(props.format),
    dayjs: dayjs
  };
};
const currentDate = ref(getCalendarDate(dayjs()));
展示的日期:因为不错切换上一年、上一月、下一月、下一年,是以展示的日期会存在和选中的日期不同的情况,也需要一个对象来记载,默许情况下展示的日期等于选中的日期
csharp 代码解读复制代码const showDate = ref(currentDate.value)
切换月份、年份:有了上头的这些,已毕起来就特别容易,修改展示日期,然后把柄展示日期再行得回6*7的日期列表
ini 代码解读复制代码const nextMonth = (number) => {
  showDate.value = getCalendarDate(showDate.value.dayjs.add(number, "month"));
  dateList.value = getDateList();
};
const nextYear = (number) => {
  showDate.value = getCalendarDate(showDate.value.dayjs.add(number, "year"));
  dateList.value = getDateList();
};
修将来期:相通只需要修改组中日期、展示日期,然后把柄展示日期再行得回日期列表,同期抛出一个change事件,给外部使用
ini 代码解读复制代码const emit = defineEmits(["change"]);
const handleChangeCurrent = (dayjs: Dayjs) => {
  currentDate.value = getCalendarDate(dayjs);
  showDate.value = currentDate.value;
  dateList.value = getDateList();
  emit("change", currentDate.value);
};
小红点、非面前月日期灰色展示:这些即是一些纰漏的判断了,把柄展示日期和选中日期来判断就行
ini 代码解读复制代码<td v-for="date in dateList.slice((row - 1) * 7, (row - 1) * 7 + 7)" :key="date.value">
  <div
    class="calendar-date hand"
    :class="{
      'calendar-date--grey': date.month !== showDate.month,
      'calendar-date--today': date.value === currentDate.value
    }"
    @click="handleChangeCurrent(date.dayjs)"
  >
    <span>{{ date.date }}</span>
    <span v-if="props.dotDays.includes(date.value)" class="calendar-dot"></span>
  </div>
</td>
源码
xml 代码解读复制代码<template>
  <div class="calendar">
    <div class="calendar-header">
      <div class="calendar-header__left">
        <el-icon class="hand" @click="nextYear(-1)"><DArrowLeft /></el-icon>
        <el-icon class="hand" @click="nextMonth(-1)"><ArrowLeft /></el-icon>
      </div>
      <div class="calendar-header__center">{{ showDate.year }} 年 {{ showDate.month + 1 }} 月</div>
      <div class="calendar-header__right">
        <el-icon class="hand" @click="nextMonth(1)"><ArrowRight /></el-icon>
        <el-icon class="hand" @click="nextYear(1)"><DArrowRight /></el-icon>
      </div>
    </div>
    <div class="calendar-main">
      <table class="calendar-table">
        <thead class="calendar-thead">
          <tr>
            <th v-for="(day, index) in sevenDay" :key="index">{{ day }}</th>
          </tr>
        </thead>
        <tbody class="calendar-tbody">
          <tr v-for="row in rows" :key="row">
            <td v-for="date in dateList.slice((row - 1) * 7, (row - 1) * 7 + 7)" :key="date.value">
              <div
                class="calendar-date hand"
                :class="{
                  'calendar-date--grey': date.month !== showDate.month,
                  'calendar-date--today': date.value === currentDate.value
                }"
                @click="handleChangeCurrent(date.dayjs)"
              >
                <span>{{ date.date }}</span>
                <span v-if="props.dotDays.includes(date.value)" class="calendar-dot"></span>
              </div>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>
<script lang="ts" setup>
import dayjs, { Dayjs } from "dayjs";

interface CalendarDate {
  year: number;
  month: number;
  date: number;
  value: string;
  dayjs: Dayjs;
}

interface Props {
  dotDays?: string[]; // 需要加点的日期
  format?: string; // 日期举止,必须保证举止化后的日期是独一的,默许YYYY-MM-DD(参考dayjs)
  current?: string; // 面前选中的日期,举止与format保执一致,默许聘请面前日期
  disabled?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  dotDays: () => [], // ["2023-09-19", "2023-09-20", "2023-08-31"]
  format: "YYYY-MM-DD",
  disabled: false
});
const sevenDay: Array<string> = ["日", "一", "二", "三", "四", "五", "六"];
const dateList = ref<CalendarDate[]>([]);

const getCalendarDate = (dayjs: Dayjs): CalendarDate => {
  return {
    year: dayjs.year(),
    month: dayjs.month(),
    date: dayjs.date(),
    value: dayjs.format(props.format),
    dayjs: dayjs
  };
};
// 选中的日期
const currentDate = ref<CalendarDate>(getCalendarDate(dayjs()));
// 面前日期展示的日期
const showDate = ref<CalendarDate>(currentDate.value);

// 得回日期列表,6*7天
const rows = 6;
const getDateList = (): Array<CalendarDate> => {
  const firstDay = showDate.value.dayjs.startOf("month").startOf("week");
  return Array(rows * 7)
    .fill(0)
    .map((n, i) => {
      const day = firstDay.add(i, "day");
      return getCalendarDate(day);
    });
};

const nextMonth = (number: number) => {
  showDate.value = getCalendarDate(showDate.value.dayjs.add(number, "month"));
  dateList.value = getDateList();
};
const nextYear = (number: number) => {
  showDate.value = getCalendarDate(showDate.value.dayjs.add(number, "year"));
  dateList.value = getDateList();
};

// 修改组中日期
const emit = defineEmits(["change"]);
const handleChangeCurrent = (dayjs: Dayjs) => {
  if (props.disabled) return;
  currentDate.value = getCalendarDate(dayjs);
  showDate.value = currentDate.value;
  dateList.value = getDateList();
  emit("change", currentDate.value);
};

onMounted(() => {
  if (props.current) {
    handleChangeCurrent(dayjs(props.current, props.format));
  } else {
    dateList.value = getDateList();
  }
});
</script>
<style lang="scss" scoped>
.calendar {
  user-select: none;
  .calendar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 22px;
    padding: 0 12px;
    font-size: 14px;
    color: var(--el-text-color-primary);
  }
  .calendar-main {
    padding-bottom: 12px;
    margin-top: 12px;
  }
  .calendar-table {
    width: 100%;
    th,
    td {
      // width: (100/7);
      width: 14.285%;
      min-width: 40px;
      padding: 4px 0;
      font-size: 14px;
      font-weight: 400;
      line-height: 24px;
      color: var(--el-text-color-primary);
      text-align: center;
    }
    th {
      color: #bfbfbf;
    }
  }
  .calendar-date {
    position: relative;
    width: 24px;
    height: 24px;
    margin: -1px auto;
    border-radius: 2px;
    &--grey {
      color: #bfbfbf;
    }
    &:hover {
      background: var(--el-color-primary-light-9);
    }
    &--today {
      color: #ffffff !important;
      background: var(--el-color-primary) !important;
    }
  }
  .calendar-dot {
    position: absolute;
    top: -3px;
    right: -3px;
    width: 6px;
    height: 6px;
    background-color: #fc474c;
    border-radius: 50%;
  }
}
.hand {
  cursor: pointer;
}
</style>
本站仅提供存储业绩,扫数实质均由用户发布,如发现存害或侵权实质,请点击举报。