웹 패키지가 없는 간단한 Vue 캘린더 만들기

27023 단어 vuetutorialjavascript
개발 중인 제품을 위한 달력 (또는 날짜 선택기) 이 필요합니다.과거에 나는 항상 도서관에 갔다.
달력은 통상적으로 내가 유지하고 싶은 것이 아니라, 라이브러리의 기능은 통상적으로 많은 다른 용례를 포함한다.그러나 이런 상황에서 나는 내가 몇 시간 안에 무엇을 세울 수 있는지 보고 싶다.
그러면 Vue로 캘린더를 만듭니다.단일 HTML 파일을 사용합니다.우리는 웹 팩이나babel을 사용하지 않을 것이다.우리는 어떤 것도 컴파일하거나 설치할 필요가 전혀 없다.
다음은 최종 제품의 외관입니다.


데릭

처음 사용date-fns.org, 몇 시간 안에 Vue에서 작업 달력 구성 요소를 만들 수 있습니다.즐거운 경험.과거에 나는 항상 도서관에 갔다. 왜냐하면 나는 달력이 너무 복잡해서 내가 관리할 수 없다고 생각했기 때문이다.
15:2020년 8월 22일 오후 21시
0
0
우리는 이 틀에서 시작할 것이다.그것은 우리가 일을 완성하는 데 쓰는 모든 것을 포함하고 있다.

  • tailwind: 유틸리티 우선 순위 CSS 프레임워크

  • vue: 사용자 인터페이스 구축을 위한 JavaScript 프레임워크

  • date-fns: 날짜 유틸리티 라이브러리

  • lodash: 유틸리티 라이브러리
  • <!DOCTYPE html>
    <html>
    
    <head>
      <title>Calendar.vue</title>
      <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
      <script src="https://unpkg.com/vue"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js"
        integrity="sha512-F+u8eWHrfY8Xw9BLzZ8rG/0wIvs0y+JyRJrXjp3VjtFPylAEEGwKbua5Ip/oiVhaTDaDs4eU2Xtsxjs/9ag2bQ=="
        crossorigin="anonymous"></script>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
    </head>
    
    <body class="py-12">
      <div class="container mx-auto flex justify-center">
        <div id="calendar" class="w-1/3 rounded border">
          &nbsp;
        </div>
      </div>
    
      <script>
        var app = new Vue({
          el: '#calendar'
        })
      </script>
    </body>
    
    </html>
    
    우선 데이터 구조에서 달력을 어떻게 표시하는지 생각하는 것이 도움이 된다.이것이 바로 내가 생각하는 모습이다.
    var august2020 = [
      [null, null, null, null, null, null, 1],
      [2, 3, 4, 5, 6, 7, 8],
      [9, 10, 11, 12, 13, 14, 15],
      [16, 17, 18, 19, 20, 21, 22],
      [23, 24, 25, 26, 27, 28, 29],
      [30, 31, null, null, null, null, null]
    ]
    
    DOM 요소에 쉽게 매핑할 수 있는 데이터 구조를 원합니다.만약 우리가 august2020을 본다면, 우리는 모든 수조가 달력의 한 줄이 되고, 수조의 모든 값이 div에 어떻게 비치는지 볼 수 있다.null 값은 비어 있습니다div.
    도전은 매달 변화가 발생할 때 이런 데이터 구조를 구축해야 한다는 것이다.한 달은 일주일의 어느 날에나 시작하고 끝날 수 있기 때문에 우리는 알고리즘을 생각해 내야 한다.
    시작합시다.
    우리는 세 개의 함수가 필요하다.한 사람이 그 달을 얻는 첫날, 한 사람이 그 달을 얻는 마지막 날, 한 사람이 그 달을 얻는 일수.우리는 이 함수를 사용하여 달력을 어디서부터 그릴지 결정할 것이다.다시 말하면 우리가 1을 그리기 전에 얼마나 많은 빈 원소가 필요하고, 31을 그린 후에 얼마나 많은 빈 원소가 필요하냐는 것이다.
    var app = new Vue({
      el: '#calendar',
      data: {
        // August 1, 2020
        date: new Date(2020, 7, 1)
      },
      computed: {
        startOfMonth: function() {
          return dateFns.startOfMonth(this.date)
        },
        endOfMonth: function() {
          return dateFns.endOfMonth(this.date)
        },
        daysInMonth: function() {
          return dateFns.getDaysInMonth(this.date)
        }
      }
    })
    
    dateFns 대상은date fns에서 제공합니다.우리가 호출한 함수는 당신이 원하는 기능을 실현했습니다. (훌륭하죠?)
    일단 우리가 월초와 월말이 생기면, 우리는 상기 august2020 데이터 구조를 구축할 충분한 시간이 있다.우리는 2020년 8월의 몇 주 내에 건설할 것이다.우리는 주간을 사용하여 페이지에 2020년 8월을 표시할 것이다.
    <body class="py-12">
      <div class="container mx-auto flex justify-center">
        <div id="calendar" class="w-1/3 rounded border">
          <section>
            <ul v-for="(week, weekIndex) in weeks" :key="weekIndex" class="border-t">
              <li>
                <ul class="flex">
                  <li v-for="(day, dayIndex) in week" :key="`${weekIndex}-${dayIndex}`" class="flex-1 p-1 text-center border-r last:border-r-0">
                    {{day && day.getDate()}}
                  </li>
                </ul>
              </li>
            </ul>
          </section>
        </div>
      </div>
    
      <script>
        var app = new Vue({
          el: '#calendar',
          data: {
            // August 1, 2020
            date: new Date(2020, 7, 1)
          },
          computed: {
            startOfMonth: function() {
              return dateFns.startOfMonth(this.date)
            },
            endOfMonth: function() {
              return dateFns.endOfMonth(this.date)
            },
            daysInMonth: function() {
              return dateFns.getDaysInMonth(this.date)
            },
            weeks: function() {
              var firstDayOfWeek = dateFns.getDay(this.startOfMonth)
    
              var days = []
    
              for (var i = 0; i < firstDayOfWeek; i++) {
                days.push(null)
              }
    
              for (var i = 1; i <= this.daysInMonth; i++) {
                days.push(dateFns.setDate(this.date, i))
              }
    
              var lastDayOfWeek = dateFns.getDay(this.endOfMonth)
              for (var i = 0; i < 6 - lastDayOfWeek; i++) {
                days.push(null)
              }
    
              return _.chunk(days, 7)
            }
          }
        })
      </script>
    </body>
    
    상기 코드의 결과는 다음과 같다.우리 그것을 분해합시다.

    일단 우리가 일주일의 첫날(2020년 8월 토요일부터)을 확정하면, 우리는 얼마나 많은 공백이 필요한지 계산할 수 있다.이런 상황에서 우리는 여섯 개의 공백이 필요하다.0에서 5까지의 순환이 이 결과를 가져올 것이다.이때 days 수조는 다음과 같다. [null, null, null, null, null, null].
    for (var i = 0; i < firstDayOfWeek; i++) {
      days.push(null)
    }
    
    이때, 우리는 1-31일을 추가할 수 있다. 왜냐하면 우리는 8월에 31일이 있다는 것을 알고 있기 때문이다.1부터 31까지의 순환으로 임무를 완성할 수 있다.우리는 정수를 사용하지 않고 Date 개의 대상을 밀어 넣었다.우리는 dateFns.setDate(this.date, i) 을 사용하여 새 날짜 대상을 i 의 값으로 설정합니다.이것은 다른 목적에 편의를 가져다 줄 것이다.
    이 검색을 실행하면 days 은 6개의 빈 값을 가진 그룹으로 정수 1부터 31까지 뒤따릅니다.
    for (var i = 1; i <= this.daysInMonth; i++) {
      days.push(dateFns.setDate(this.date, i))
    }
    
    마지막으로, 일단 우리가 완성되면, 우리는 한 달의 마지막 날로 우리가 달력의 나머지 부분에 얼마나 많은 공백을 채워야 하는지 확인할 수 있다.2020년 8월은 월요일에 끝나기 때문에 우리는 다섯 개의 공백을 메워야만 완성할 수 있다.여기에는 0에서 4까지의 순환이 있다.
    for (var i = 0; i < 6 - lastDayOfWeek; i++) {
      days.push(null)
    }
    
    이제 라벨을 추가합시다.이를 위해서는 HTML과 포맷 함수가 필요합니다.우리는 2020년 8월을 상단에 표시하고 일주일의 매일에 라벨을 추가하기를 희망합니다.
    주 및 일 표시를 위해 <section> 바로 위에 있는 Vue 템플릿에 다음 내용을 추가합니다.
    <section class="flex">
      <h2 class="flex-grow text-center text-lg font-bold">{{month}}</h2>
    </section>
    <ul class="flex bg-gray-100 border-t text-gray-600">
      <li class="flex-1 text-center border-r last:border-r-0">S</li>
      <li class="flex-1 text-center border-r last:border-r-0">M</li>
      <li class="flex-1 text-center border-r last:border-r-0">T</li>
      <li class="flex-1 text-center border-r last:border-r-0">W</li>
      <li class="flex-1 text-center border-r last:border-r-0">R</li>
      <li class="flex-1 text-center border-r last:border-r-0">F</li>
      <li class="flex-1 text-center border-r last:border-r-0">S</li>
    </ul>
    
    month의 함수도 간단한 함수이다.마찬가지로, dateFnsdatefns에서 제공하며, 우리는 그 형식 함수를 사용합니다.'MMMM YYYY' 2020년 8월과 유사한 날짜를 나타내는 문자열 표시일 뿐이다.
    function() {
      return dateFns.format(this.date, 'MMMM YYYY')
    }
    
    이것은 우리로 하여금 여기까지 오게 했다.다음은 달력의 현재 모습이다.

    우리가 해야 할 마지막 일은 지난달과 다음 달로 내비게이션하는 것이다.이것은 재미있는 부분이다.지금까지 우리가 한 모든 것은 Vue의 가장 강력한 기능인 반응성을 사용하기 위해서였다.
    Vue는 변경될 때마다 이미 작성한 코드를 다시 사용하고 새 날짜에 따라 새 달력을 그립니다.따라서 만약 우리가 날짜를 2020년 7월로 바꾸면, 우리는 2020년 7월의 달력을 그릴 것이다.우리 합시다.
    우선, 우리는 몇 개의 링크를 눌러야 한다.우리는'이전'을 말하는 링크와'다음'을 말하는 링크가 필요하다.이런 일은 매우 좋다.
    <section class="flex">
      <a class="ml-4 flex-shrink cursor-pointer text-gray-800 underline">Previous</a>
      <h2 class="flex-grow text-center text-lg font-bold">{{month}}</h2>
      <a class="ml-4 flex-shrink cursor-pointer text-gray-800 underline">Next</a>
    </section>
    
    네가 알 수 있는 바와 같이, 이 링크들은 아무런 작용도 하지 않는다.우리는 그것들을 Vue에 연결하지 않았지만, 이것은 매우 쉽다. 이렇게 하자.링크를 눌렀을 때 이 방법을 사용할 수 있는 방법이 필요합니다.이전 링크는 월 1 감소, 다음 링크는 월 1 증가.
    // ...
    methods: {
      changeMonth: function(by) {
        this.date = dateFns.addMonths(this.date, by)
      }
    }
    // ...
    
    <section class="flex">
      <a v-on:click="changeMonth(-1)" class="ml-4 flex-shrink cursor-pointer text-gray-800 underline">Previous</a>
      <h2 class="flex-grow text-center text-lg font-bold">{{month}}</h2>
      <a v-on:click="changeMonth(1)" class="ml-4 flex-shrink cursor-pointer text-gray-800 underline">Next</a>
    </section>
    
    이전 링크를 클릭하면 Vue는 함수를 호출합니다. 매개변수는 -1입니다.그리고 우리의 함수는 현재 날짜(즉 2020년 8월 1일)를 토대로 -1개월을 더한다.이것은 Vue가 2020년 7월을 현재 날짜로 우리의 구성 요소를 다시 렌더링하는 것을 알려 줍니다.우리 끝났어.

    If you'd like to view the full version, check it out on JSFiddle. 로컬 시스템에 복사하여 붙여넣은 다음 사용하십시오.
    그게 유용하다고 생각하면

    좋은 웹페이지 즐겨찾기