[vue calendar project] 자바스크립트로 캘린더 만들기 -3

캘린더 라이브러리 없이 자바스크립트로 캘린더를 만들었다.


1. 이번 달 캘린더를 출력해보자.

이번 달 달력 안에는 해당하는 달의 날짜들뿐만 아니라 그 이전 달의 마지막 주와 다음 달의 첫번째 주가 포함되어 있다. 따라서 지난 달의 마지막 날짜, 이번달의 마지막 날짜, 다음달의 첫날 데이터가 필요하다.

달력을 랜더링 할 기준 날짜 (첫날, 마지막 날 날짜) 구하기

인스턴스가 생성되면 캘린더를 랜더할 수 있도록 created()에 작성했다.

created() {
     this.year = this.today.getFullYear();
     this.month = this.today.getMonth();
     this.date = this.today.getDate();
     this.getDates(); // 달력의 전체 날짜를 출력하는 함수
}

먼저, 올해 이번 달을 기준으로 데이터를 return 하는 함수를 작성한다.

함수 정의
methods: {
  getFirstAndLastDate(month, year){
            const lastMonthLastDate = new Date(year, month, 0).getDate();
            const lastMonthLastDay = new Date(year, month, 0).getDay();
            const thisMonthLastDate = new Date(year, month+1, 0).getDate();
            const nextMonthFirstDay = new Date(year,month+1).getDay();
            return [this.lastMonthLastDate=lastMonthLastDate, this.lastMonthLastDay=lastMonthLastDay, 
            this.thisMonthLastDate=thisMonthLastDate, this.nextMonthFirstDay=nextMonthFirstDay];
     },
}
함수 호출
methods: {
   getDates(){
    	const [lastMonthLastDate, lastMonthLastDay, thisMonthLastDate, nextMonthFirstDay] = 
            this.getFirstAndLastDate(this.currentMonth, this.currentYear);
   }
}

그 날짜를 기준으로 지난달 마지막 날짜, 지난달 마지막 날짜의 요일, 이번달의 마지막 날짜, 다음 달의 첫째 날 요일을 차례로 구한다.
달력의 일주일에 해당하는 date들을 week 배열에 먼저 push 한 뒤, 해당 week의 length가 7이라면 전체 달력 날짜를 나타내는 dates 배열에 할당하고, 이 후 week 배열을 빈 배열로 return 해준다. 이로써 일주일씩 데이터를 push할 수 있게 된다.

지난 달 마지막 주, 이번달, 다음 달 첫 주 순으로 출력해보자.

지난 달 마지막 주 출력하기

함수 정의
methods: {
	getPrevMonth(prevLastDate, prevLastDay){
            if(prevLastDay!==6){
                for(let date = prevLastDate-prevLastDay; date <= prevLastDate; date++){
                    this.week.push(date);
                    this.checkLength();
                }
            }
        }
}
함수 호출
this.getPrevMonth(lastMonthLastDate,lastMonthLastDay);

이번 달 출력하기

함수 정의
methods: {
	getThisMonth(thisMonthLastDate){
                for(let date = 1; date<=thisMonthLastDate; date++){
                    this.week.push(date);
                    this.checkLength();
                }
        }
}
함수 호출
this.getThisMonth(thisMonthLastDate);

다음 달 첫째 주 출력하기

함수 정의
methods: {
	getNextMonth(nextMonthFirstDay){
            if(nextMonthFirstDay!==0){
                for(let date = 1 ; date <= 7-nextMonthFirstDay; date++){
                    this.week.push(date);
                    this.checkLength();
                }
           }
        }
}
함수 호출
this.getNextMonth(nextMonthFirstDay);

캘린더에 날짜 출력

<table class="table table-responsive">
   <thead>
      <tr>
         <th scope="col" v-for="day in days" :key="day">{{ day }}</th> //요일 출력
      </tr>
   </thead>
   <tbody>
      <tr v-for="(weeks, FirstIdx) in dates" :key="FirstIdx">
        <td scope="row" v-for="(date, SecondIdx) in weeks" :key="SecondIdx">
        	<div>{{ date }}</div>
        </td>
      </tr>
   </tbody>
</table>

2. 이전, 다음 달로 넘어가기

화살표를 눌러 다음 달, 이전 달로 넘어가보자.
먼저 다른 달로 넘어가면 해당 month를 기준으로 하는 캘린더 날짜를 다시 계산해서 랜더링 해줘야 하기 때문에, 이전 이후 버튼을 눌러 이동한 값 만큼 month를 다시 계산해서 month를 업데이트 해줘야 한다. 이때 기존 month 데이터와 계산된 month를 구분하기 위해 계산된 month는 currentMonth로 지정.

이전 이후 버튼 클릭할 때마다 month값에 -1또는 1 계산

전체 날짜를 랜더링하는 getDates()에 파라미터를 넘겨, 이전 버튼을 클릭하면 currnetMonth-1, 다음 버튼을 클릭하면 currentMonth+1로 계산되도록 파라미터를 전달한다.

getDates(param =0){
  if(param === 1){
                  this.currentMonth++;
                  if(this.currentMonth === 12){
                      this.currentMonth = 0;
                      this.currentYear++;
                  }
              }
              if(param === -1){
                  this.currentMonth--;
                  if(this.currentMonth === -1){
                      this.currentMonth = 11;
                      this.currentYear--;
                  }
              }
  }

currentMonth로 달력을 랜더링 할 기준 날짜 구하기

update 된 currentmonth로 getFirstAndLastDate()호출한다. 이 후 update 된 기준 날짜를 기반으로 캘린더를 재랜더링 해준다.



3. 지난 달 마지막 주와 다음 달 첫 주, 오늘 날짜 표시

클래스 바인딩을 통해 구분해준다.

<td scope="row" v-for="(date, SecondIdx) in weeks" :key="SecondIdx"
          :class="{'today': isToday(date, dates, FirstIdx, SecondIdx),
                   'prev-or-next-month': isPrevOrNextMth(dates, FirstIdx, SecondIdx)}"
           class="date">
           <div>{{ date }}</div>
</td>

지난 달 마지막 주와 다음 달 첫 주

isPrevOrNextMth(dates, FirstIdx, SecondIdx){
            if((FirstIdx===0 && SecondIdx <= this.lastMonthLastDay && (this.lastMonthLastDay!==6))
                || ((FirstIdx === dates.length-1 && SecondIdx >= this.nextMonthFirstDay) && (this.nextMonthFirstDay!==0))) 
                {
                    return true;
                }else{
                    return false;
                }
        },

오늘 날짜

isToday(date, dates, FirstIdx, SecondIdx){
            if(!(this.isPrevOrNextMth(dates, FirstIdx, SecondIdx))
                && date === this.date
                && this.currentMonth === this.month
                && this.currentYear === this.year)
                {
                    return true;
                }else{
                    return false;
            }
        }

결과

좋은 웹페이지 즐겨찾기