date-fns(Vue 3)를 사용하는 캘린더 구성 요소 예제
19704 단어 vuecalendartailwindcssvue3
먼저 몇 가지 코드를 살펴보겠습니다.
const currentDate = ref(startOfDay(new Date()));
const days = computed(() => {
const monthStart = startOfMonth(currentDate.value);
const dayNumInWeek = getDay(monthStart);
const calendarStart = subDays(monthStart, dayNumInWeek !== 0 ? dayNumInWeek - 1 : 6);
return eachDayOfInterval({
start: calendarStart,
end: addDays(calendarStart, 41)
}).map((date) => {{
return {
isCurrent: compareAsc(currentDate.value, date) === 0,
isCurrentMonth: date.getMonth() === currentDate.value.getMonth(),
date: date
}
}});
});
이해하기 어렵지 않고 꽤 단순해 보입니다. 그러나 즉시 이해가 되지 않는다면 단계별로 설명하겠습니다.
먼저 이번 달의 시작과 끝을 가져와야 합니다.
const monthStart = startOfMonth(currentDate.value);
const monthEnd = endOfMonth(currentDate.value);
우리의 monthStart 및 monthEnd는 Date 개체에 해당 월의 시작 날짜와 종료 날짜가 포함되어 있습니다. 따라서 이번 달이 시작되는 날짜를 알 수 있습니다.
const dayNumInWeek = getDay(monthStart)
이제 이를 사용하여 캘린더의 시작 날짜를 얻을 수 있습니다.
const calendarStart = subDays(monthStart, dayNumInWeek !== 0 ? dayNumInWeek - 1 : 6);
달력에 7주를 표시하고 이번 달의 첫 번째 날은 어느 요일이든 될 수 있기 때문에 필요합니다. 때로는 주 컨텍스트에서 해당 월의 첫 번째 날이 0(일요일)일 수 있으며 이러한 일이 발생하면 6일을 줄여야 합니다.
마지막으로 우리는 한 번에 42일을 표시하고 유용한 개체로 매핑하기를 원하기 때문에 calendarStart와 calendarStart + 41 사이의 간격을 가져와야 합니다.
eachDayOfInterval({
start: calendarStart,
end: addDays(calendarStart, 41)
}).map((date) => {{
return {
isCurrent: compareAsc(currentDate.value, date) === 0,
isCurrentMonth: date.getMonth() === currentDate.value.getMonth(),
date: date
}
}});
마지막으로 Vue 3 및 Tailwind를 사용하여 전체 예제 코드를 구현해 보겠습니다.
<template>
<div class="w-60 bg-white dark:border-[1px] dark:border-gray_border dark:bg-gray_800 rounded-lg shadow-lg">
<div class="flex justify-center space-x-2 py-3 items-center rounded-lg">
<button
type="button"
class="-my-1.5 flex flex-none items-center justify-center p-1.5"
@click="toPreviousMonth"
>
<span class="sr-only">Previous month</span>
<!-- Heroicon name: solid/chevron-left -->
<svg class="h-5 w-5 icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"
aria-hidden="true">
<path fill-rule="evenodd"
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
clip-rule="evenodd"/>
</svg>
</button>
<h2 class="font-normal text-gray_800 text-sm dark:text-white font-inter">
{{ format(currentDate, 'MMMM yyyy') }}
</h2>
<button
type="button"
class="-my-1.5 -mr-1.5 ml-2 flex flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500"
@click="toNextMonth"
>
<!-- Heroicon name: solid/chevron-right -->
<svg class="h-5 w-5 icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"
aria-hidden="true">
<path fill-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clip-rule="evenodd"/>
</svg>
</button>
</div>
<div class="mt-2 grid grid-cols-7 text-center text-sm">
<div class="text-gray_500 font-inter dark:text-white">Mo</div>
<div class="text-gray_500 font-inter dark:text-white">Tu</div>
<div class="text-gray_500 font-inter dark:text-white">We</div>
<div class="text-gray_500 font-inter dark:text-white">Th</div>
<div class="text-gray_500 font-inter dark:text-white">Fr</div>
<div class="text-gray_500 font-inter dark:text-white">Sa</div>
<div class="text-gray_500 font-inter dark:text-white">Su</div>
</div>
<div class="mt-2 grid grid-cols-7 text-sm font-inter">
<button
v-for="(day, index) in days" :key="`day-${index}`"
type="button"
class="mx-auto flex h-8 w-8 items-center justify-center rounded-lg"
@click="currentDate = day.date"
:class="{'bg-blue_400 justify-center rounded-lg': day.isCurrent}"
>
<time :class="{
'text-number_calendar': !day.isCurrentMonth,
'text-gray_800 dark:text-white': day.isCurrentMonth
}">
{{ format(day.date, 'd') }}
</time>
</button>
</div>
</div>
</template>
<script setup lang="ts">
import {
subDays,
addDays,
eachDayOfInterval,
format,
startOfMonth,
compareAsc,
startOfDay,
addMonths,
subMonths,
getDay,
} from 'date-fns'
import {computed, ref} from "vue";
const currentDate = ref(startOfDay(new Date()));
const days = computed(() => {
const monthStart = startOfMonth(currentDate.value);
const dayNumInWeek = getDay(monthStart);
const calendarStart = subDays(monthStart, dayNumInWeek !== 0 ? dayNumInWeek - 1 : 6);
return eachDayOfInterval({
start: calendarStart,
end: addDays(calendarStart, 41)
}).map((date) => {{
return {
isCurrent: compareAsc(currentDate.value, date) === 0,
isCurrentMonth: date.getMonth() === currentDate.value.getMonth(),
date: date
}
}});
});
function toNextMonth() {
currentDate.value = addMonths(startOfMonth(currentDate.value), 1)
}
function toPreviousMonth() {
currentDate.value = subMonths(startOfMonth(currentDate.value), 1)
}
</script>
Reference
이 문제에 관하여(date-fns(Vue 3)를 사용하는 캘린더 구성 요소 예제), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/davidnadejdin/calendar-component-example-with-date-fns-vue-3-5dm9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)