개발자 혜진
꾸준하게 개발 블로그
개발자 혜진
05-24 09:13
전체 방문자
오늘
어제
  • 전체보기 (69)
    • 코딩테스트 (25)
    • HTML (1)
    • CSS (6)
    • React (3)
    • Vue (8)
    • Javascript (9)
    • Java (3)
    • IDE (1)
    • Toy Project (10)
    • 개발 서적 (2)
    • 개발 이야기 (0)
    • TMI (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 글쓰기

인기 글

태그

  • 이상한문자만들기 js
  • react
  • vuetify
  • 텍스트에그라데이션
  • js 진수변환
  • vue2
  • 프로그래머스 3진법뒤집기
  • 박스가운데정렬
  • spring boot 한글 깨짐
  • 클래스 토글
  • Java초기화
  • div가운데정렬
  • springboot mustache 한글 깨짐
  • 프로그래머스
  • vue2캘린더 만들기
  • input Foucs Out
  • 텍스트에이미지적용
  • 프로그래머스예산
  • 드로잉윗유
  • 프로그래머스0
  • 뷰티파이
  • 시저암호javascript
  • styled-component focus out
  • TypeScript기본문법
  • 시저암호js
  • 8진수2진수
  • classList메소드
  • 예산js
  • javascript 진수
  • 가로가운데정렬

최근 글

hELLO · Designed By 정상우.
개발자 혜진

꾸준하게 개발 블로그

Vue

[Vue 2]캘린더 만들기

2023. 2. 1. 01:12

직접 라이브러리를 사용하지 않고,  캘린더를 제작해보려고 합니다.

직접 만들어보면서 게시글을 작성중입니다.

그래서..아직 css나 접근성 부분에서 많이 모자라요!

조금이나마 도움이 되었으면 좋겠습니다.

<template>
  <div>
    <div>
      <button type="button" @click="changeMonth(-1)">&lt;</button>
      {{ calendarHeader }}
      <button type="button" @click="changeMonth(1)">&gt;</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)">&lt;</button>
      {{ calendarHeader }}
      <button type="button" @click="changeMonth(1)">&gt;</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
    'Vue' 카테고리의 다른 글
    • [Vue2] vue이용해서 캘린더 만들기 2
    • [Vue 2] vue-router 설정하기
    • [Vue 2] axios 모듈화 하기
    • [Vue 2] vuetify icon custom 하기
    개발자 혜진
    개발자 혜진
    잊어버리지 않기위한 개발 블로그

    티스토리툴바