직접 라이브러리를 사용하지 않고, 캘린더를 제작해보려고 합니다.
직접 만들어보면서 게시글을 작성중입니다.
그래서..아직 css나 접근성 부분에서 많이 모자라요!
조금이나마 도움이 되었으면 좋겠습니다.

<template>
<div>
<div>
<button type="button" @click="changeMonth(-1)"><</button>
{{ calendarHeader }}
<button type="button" @click="changeMonth(1)">></button>
</div>
<table>
<thead>
<tr>
<th v-for="index in week" :key="index">
{{ index }}
</th>
</tr>
</thead>
<tbody>
<!-- days의 index 만큼 tr 반복 -->
<tr v-for="(index, i) in days" :key="i">
<!-- days의 index의 childIndex만큼 td 반복 -->
<td v-for="childIndex in index" :key="childIndex">{{ childIndex }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'DatePicker',
data() {
return {
today: new Date(),
week: ['일', '월', '화', '수', '목', '금', '토'],
calendarHeader: '',
days: [],
};
},
mounted() {
this.calendarImplementation();
},
methods: {
calendarImplementation: function () {
//달이 변경 되었을때를 위해 배열 초기화
this.days = [];
const year = this.today.getFullYear();
const month = this.today.getMonth();
//시작 요일 찾기
const startDayOfTheMonth = new Date(year, month, 1).getDay();
//마지막 날 찾기
const endDayOfTheMonth = new Date(year, month + 1, 0).getDate();
//마지막 날까지 채우기 [1,2,3,...,30,31]
const basicDays = Array.from({ length: endDayOfTheMonth }, (v, i) => i + 1);
//시작하는 요일까지의 빈 날짜 채우기
//시작 요일이 수요일이면 startDayOfTheMonth의 값이 3 [null, null, null]
const emptyDays = Array(startDayOfTheMonth).fill(null);
//두 배열 합치기 [null,null,null, 1, 2,...,31]
const combinedDays = [...emptyDays, ...basicDays];
//7일씩 나눠주기
for (let i = 0; i < endDayOfTheMonth + startDayOfTheMonth; i += 7) {
this.days.push(combinedDays.slice(i, i + 7));
}
this.calendarHeader = `${year}년 ${month + 1} 월`;
},
changeMonth: function (val) {
//달력 옮기기
this.today = new Date(this.today.setMonth(this.today.getMonth() + val, 1));
this.calendarImplementation();
},
},
};
</script>
<tr v-for="(index, i) in days" :key="i">
<!-- days의 index의 childIndex만큼 td 반복 -->
<td v-for="childIndex in index" :key="childIndex">{{ childIndex }}</td>
</tr>
이부분을 보시면 두개의 for문이 다르죠?!
그 이유는 days의 index의 내용이 string, number가 아니기 때문인데요.
vue의 key값은 string,number여야합니다.
key값으로 index를 사용하기위해 한번 더 감싸줬습니다!
이제 주말을 표시해주려고 하는데요. 문제가 생겼습니다.
마지막 주의 경우는 공백을 추가해주지 않았었는데요.
tr td:first-child,
tr th:first-child {
color: red;
}
tr td:last-child,
tr th:last-child {
color: blue;
}
이렇게 해주니 마지막 날의 색상이 토요일이 아닌데도 변경이 되었습니다. 그럼 바로 해결해 주도록 하겠습니다.
addLastWeekEmptyDays: function () {
const daysLastIndex = this.days.length - 1;
if (this.days[daysLastIndex] !== 7) this.days[daysLastIndex].length = 7;
},
days의 길이를 가져와서 7과 비교해주고, 그렇지 않으면 마지막 주의 길이를 7로 만들어 주는 코드입니다.
저번에 앞을 채울땐 fill을 사용했는데 이번엔 사용을 하지 못한 이유있습니다.
fill의 매개변수를 살펴보면 fill(value, start, end)이렇게 되어있는데요! fill은 배열의 길이만큼 밖에 채울수가 없습니다.
그래서 this.days의 마지막 인덱스의 길이를 7로 변경해주는 것으로 해결했습니다.
여기까지의 최종 코드는 더보기를 눌러주세요!
더보기
<template>
<div id="calendarSection">
<div>
<button type="button" @click="changeMonth(-1)"><</button>
{{ calendarHeader }}
<button type="button" @click="changeMonth(1)">></button>
</div>
<table>
<thead>
<tr>
<th v-for="index in week" :key="index">
{{ index }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(index, i) in days" :key="i">
<td v-for="childIndex in index" :key="childIndex">
{{ childIndex }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'DatePicker',
data() {
return {
today: new Date(),
week: ['일', '월', '화', '수', '목', '금', '토'],
calendarHeader: '',
days: [],
};
},
mounted() {
this.calendarImplementation();
},
methods: {
calendarImplementation: function () {
this.days = [];
const year = this.today.getFullYear();
const month = this.today.getMonth();
const startDayOfTheMonth = new Date(year, month, 1).getDay();
const endDayOfTheMonth = new Date(year, month + 1, 0).getDate();
const basicDays = Array.from({ length: endDayOfTheMonth }, (v, i) => i + 1);
const emptyDays = Array(startDayOfTheMonth).fill(null);
const combinedDays = [...emptyDays, ...basicDays];
for (let i = 0; i < endDayOfTheMonth + startDayOfTheMonth; i += 7) {
this.days.push(combinedDays.slice(i, i + 7));
}
this.calendarHeader = `${year}년 ${month + 1} 월`;
this.addLastWeekEmptyDays();
},
addLastWeekEmptyDays: function () {
const daysLastIndex = this.days.length - 1;
if (this.days[daysLastIndex] !== 7) this.days[daysLastIndex].length = 7;
},
changeMonth: function (val) {
this.today = new Date(this.today.setMonth(this.today.getMonth() + val, 1));
this.calendarImplementation();
},
},
};
</script>
<style>
#calendarSection {
text-align: center;
text-align: -webkit-center;
text-align: -moz-center;
}
table {
width: 100%;
}
td {
width: 40px;
height: 50px;
text-align: center;
vertical-align: baseline;
}
tr td:first-child,
tr th:first-child {
color: red;
}
tr td:last-child,
tr th:last-child {
color: blue;
}
</style>
'Vue' 카테고리의 다른 글
[Vue2] vue이용해서 캘린더 만들기 2 (0) | 2023.05.25 |
---|---|
[Vue 2] vue-router 설정하기 (0) | 2023.01.30 |
[Vue 2] axios 모듈화 하기 (0) | 2023.01.03 |
[Vue 2] vuetify icon custom 하기 (0) | 2022.09.21 |
[Vue 2] vuetify v-date-picker custom 하기 (0) | 2022.09.20 |