シンプルなVueカレンダーを構築する


私は、私が働いている製品のためにカレンダー(または日付ピッカー)を必要としました.昔はいつも図書館に着きました.
カレンダーは通常私が自分自身を維持したいものではありません、そして、ライブラリの特徴は通常多くの異なるユースケースをカバーします.しかし、この場合、2時間で何ができるか見たかったです.
それで、Vueとカレンダーを作りましょう.つのHTMLファイルを使用します.WebpackやBabelを使用しません.何かをコンパイルしたりインストールしたりする必要はありません.
ここでは、最終製品のようになります.


デレク

初めて使用date-fns.org そして、私は、数時間でVUEで働くカレンダー構成要素をまとめることができました.楽しい経験.私はカレンダーがあまりに複雑であると思ったので、過去に、私は常に図書館に着きます.
午後15時21分- 2020年8月22日
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 .
    課題は、月が変更されるときはいつでも、このデータ構造を構築する必要があることです.月は始まることができて、週のどんな日にでも終わるので、我々はアルゴリズムを考え出す必要があります.
    始めましょう.
    我々は3つの機能を必要とするつもりです.つは月の最初の日を取得するには、1つの月の最後の日を取得し、1つの月の日数を取得します.これらの関数を使用して、カレンダーの描画場所を決定します.言い換えると、私たちが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)
        }
      }
    })
    
    The 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月20日土曜日)を決定すると、我々はどのように多くの空白が必要を把握することができます.この場合、6つの空白が必要です.0から5まで行くループは、ちょうどそれを与えます.この時点でdays 配列は以下のようになります:[null, null, null, null, null, null] .
    for (var i = 0; i < firstDayOfWeek; i++) {
      days.push(null)
    }
    
    この時点で、我々は8月31日が知っているので、我々は日1 - 31日を追加することができます.1から31までのループは、仕事を得ることができます.整数を使う代わりにDate オブジェクト.使用するdateFns.setDate(this.date, i) 新しい日付オブジェクトをi . これは便利に他の目的のために来る.
    この後、実行します.days は、NULL値が6の配列で、整数1から31まで続く.
    for (var i = 1; i <= this.daysInMonth; i++) {
      days.push(dateFns.setDate(this.date, i))
    }
    
    最後に、一度我々が完了したら、我々はカレンダーの残りの部分に記入する必要がありますどのように多くの空白を決定するために月の最後の日を使用することができます.2020年8月は月曜日に終わります、それで、我々は終わりまで5つの空白を満たす必要があります.0から4へのループはここに役立つことです.
    for (var i = 0; i < 6 - lastDayOfWeek; i++) {
      days.push(null)
    }
    
    さて、ラベルを追加しましょう.そのためには、HTMLと書式設定機能が必要です.我々は、2020年8月20日には、各曜日のラベルでトップに表示したい.
    我々は、上記のVueテンプレートに直接次のを追加します<section> 週と日を表示するために.
    <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 も簡単です.再び.dateFns 日付fnsによって提供され、私たちは、その書式機能を使用します.'MMMM YYYY' ちょうど2020年8月のような日付の文字列表現を与えます.
    function() {
      return dateFns.format(this.date, 'MMMM YYYY')
    }
    
    それをすることは、我々にこの点を得ます.ここでは、カレンダーはNのように見えるものです.

    我々がする必要がある最後のことは、前と次の月に移動することができます.これは楽しい部分です.我々がこれまでにしたすべては、Vueの最も強力な特徴:反応性を使うために我々をセットアップしています.
    いつでもdate 変更は、Vueは我々が既に書いたコードを再利用し、新しい日付に基づいて新しいカレンダーを描画します.それで、2020年7月に日付を変更すると、2020年7月20日のカレンダーが私たちのために引かれます.それをしましょう.
    まず最初に、私たちはクリックするカップルリンクが必要です.「前」と「次へ」というリンクが必要です.このようなことはちょうどうまくいくでしょう.
    <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. お気軽にコピーして、ローカルマシンに貼り付けて、それを再生します.
    あなたがこれが役に立つならば、...