无需Webpack,使用一个HTML文件构建简单的Vue日历

作者 : IT 大叔 本文共5238个字,预计阅读时间需要14分钟 发布时间: 2020-08-26

我需要我正在使用的产品的日历(或日期选择器)。

日历通常不是我想要维护的东西,并且库中的功能通常涵盖许多不同的用例。但是,在这种情况下,我想看看我可以在几个小时内完成什么。

因此,让我们使用Vue构建日历。我们将使用一个HTML文件。我们不会使用webpack或babel。我们根本不需要编译或安装任何东西。

我们将从这个模板开始。它包含我们将用于完成工作的所有内容。

  • 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/lodash@4.17.20/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,可以看到每个数组如何在日历中成为一行,并且数组中的每个值可以映射到一个divnull值将为空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>

以上代码的结果如下所示。让我们分解一下。

无需Webpack,使用一个HTML文件构建简单的Vue日历插图

一旦确定了一周的第一天(2020年8月从星期六开始),我们就可以算出我们需要多少空白。在这种情况下,我们需要六个空白。从0到5的循环将为我们提供这一点。此时,days数组如下所示:[null, null, null, null, null, null]

for (var i = 0; i < firstDayOfWeek; i++) {
  days.push(null)
}

此时,我们可以添加1-31天,因为我们知道八月有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月的顶部显示一周中的每一天。

我们将在上方的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由date-fns提供,我们使用其format函数。'MMMM YYYY'只是说给我们一个字符串表示日期,看起来像是2020年8月。

function() {
  return dateFns.format(this.date, 'MMMM YYYY')
}

这样做使我们到了这一点。这是日历的样子。

无需Webpack,使用一个HTML文件构建简单的Vue日历插图(2)

我们需要做的最后一件事是让自己导航到上个月和下个月。这是有趣的部分。到目前为止,我们所做的一切都使我们能够使用Vue最强大的功能:反应性。

每当date更改时,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作为参数调用函数。然后,我们的函数会将-1个月添加到当前日期(即2020年8月1日)。这告诉Vue重新渲染我们的组件,并将2020年7月作为当前日期。大功告成

无需Webpack,使用一个HTML文件构建简单的Vue日历插图(4)

如果您想查看完整版本,请在JSFiddle上查看。随时将其复制并粘贴到本地计算机上,然后进行操作。

免责声明:
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » 无需Webpack,使用一个HTML文件构建简单的Vue日历

常见问题FAQ

没有金币/金币不足 怎么办?
本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
所有资源普通会员都能下载吗?
本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。

发表评论