小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Vue3實(shí)現(xiàn)一個(gè)簡(jiǎn)單的日歷組件

 hzlinhui 2024-08-03

日歷組件

需求
  • 需要展示一個(gè)簡(jiǎn)潔的日歷,支持切換展示的年份、月份,支持切換選中日期
  • 特殊日期展示小紅點(diǎn),比如如果當(dāng)日有日程,可以用小紅點(diǎn)標(biāo)注
效果展示
思路
  • 表頭:
    上一年、上一月、當(dāng)前月份展示、下一月、下一年

  • 表體:
    7列:["日", "一", "二", "三", "四", "五", "六"]
    6行:一共必須包含本月所有日期,會(huì)有兩種情況:(1)5行能展示完全(2)6行能展示完全,兼容兩種情況選擇無論什么情況都展示6行

    想清楚以上,思路就非常清晰了,我們只需要找到表格中的第一個(gè)日期,然后42個(gè)格子每個(gè)格子依次往后推一天就可以了
ini
代碼解讀
復(fù)制代碼
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); }); };

  • 選中的日期:我們需要有一個(gè)值來記錄選中的日期,方便高亮展示也方便后面切換時(shí)根據(jù)選中的日期展示當(dāng)前月份,所以定義了一個(gè)對(duì)象,默認(rèn)是選中當(dāng)前日期
ini
代碼解讀
復(fù)制代碼
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()));

  • 展示的日期:因?yàn)榭梢郧袚Q上一年、上一月、下一月、下一年,所以展示的日期會(huì)存在和選中的日期不同的情況,也需要一個(gè)對(duì)象來記錄,默認(rèn)情況下展示的日期等于選中的日期
csharp
代碼解讀
復(fù)制代碼
const showDate = ref(currentDate.value)

  • 切換月份、年份:有了上面的這些,實(shí)現(xiàn)起來就非常容易,修改展示日期,然后根據(jù)展示日期重新獲取6*7的日期列表
ini
代碼解讀
復(fù)制代碼
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(); };

  • 修改日期:同樣只需要修改選中日期、展示日期,然后根據(jù)展示日期重新獲取日期列表,同時(shí)拋出一個(gè)change事件,給外部使用
ini
代碼解讀
復(fù)制代碼
const emit = defineEmits(["change"]); const handleChangeCurrent = (dayjs: Dayjs) => { currentDate.value = getCalendarDate(dayjs); showDate.value = currentDate.value; dateList.value = getDateList(); emit("change", currentDate.value); };

  • 小紅點(diǎn)、非當(dāng)前月日期灰色展示:這些就是一些簡(jiǎn)單的判斷了,根據(jù)展示日期和選中日期來判斷就行
ini
代碼解讀
復(fù)制代碼
<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
代碼解讀
復(fù)制代碼
<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[]; // 需要加點(diǎn)的日期 format?: string; // 日期格式,必須保證格式化后的日期是唯一的,默認(rèn)YYYY-MM-DD(參考dayjs) current?: string; // 當(dāng)前選中的日期,格式與format保持一致,默認(rèn)選擇當(dāng)前日期 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())); // 當(dāng)前日歷展示的日期 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>

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多