Vue实现日历小插件


Posted in Javascript onJune 26, 2019

本文实例为大家分享了Vue实现日历小插件的具体代码,供大家参考,具体内容如下

先看下效果图吧, 如下

源码可见于我的github

Vue实现日历小插件

实现关键点:

1.组件的复用以及父子组件传值

很明显每年每个月的月历样式(数据不一样)是一致的,那么自然而然思路就是把每个月作为一个公用组件进行复用十二次,这样就避免了多次重复的代码。每个组件不一样的地方在于年份和月份,而这两个数据我们可以由父组件向子组件进行传值来告诉子组件。关键代码如下:

<template>
 <div class="wrap">
//months是一个包含十二个月名字的数组,用v-for对其进行循环渲染,并且把月份的index传给子组件
  <div v-for='(items, index) in months' v-if="index == monthIndex">
  <month :monthName='items' 
        :year='year' //年份传给子组件,年份在mounted里面计算得出
        :monthIndex='index' //月份传给子组件
        :day='today'//当日日期传给子组件
        :key='index' >
    </month>
  </div>
 </div>
</template>
 
//data部分
 data () {
   return {
   monthIndex: 0,
   months:['January', 'February', 'March', 'April', 
          'May', 'June', 'July', 'August', 
          'September', 'October', 'November', 'December'],
   year:-1,
   day:-1,
   }
  },

2.实现默认当日选中并且切换月份的时候其他月份不会有选中样式

在父组件的mounted钩子里面我们会计算当年当月当日,并传给子组件,子组件的有个day属性用于存储父组件传来的today的值,day属性默认值为-1,父组件传值过去之后会给day属性重新赋值

//父组件 
mounted () {
  let myDate = new Date();
  this.monthIndex = myDate.getMonth();
  this.year = myDate.getFullYear(); 
  this.today = myDate.getDate() - 1;
  },

在子组件循环渲染每天的日期的时候会设置一个动态绑定样式类似于一下代码(实际代码略微不一样):

//index值为0-41
<div v-for="(item, index) in days" :key='index' 
class="dayIndex" @click='choose(index)' 
:class="{choose: day == index}"> //动态绑定样式

当data中的属性day的值和index的值相等的时候,就会给div添加一个choose的样式,但是这样有一个问题——那就是每个月的该index的div都会有这个class样式。

解决办法:在mounted里面做个判断,如果为当月,则给data里面的day赋值,否则不做改动仍为-1,-1在循环渲染日期的时候没有对应的index,所以不会产生选中样式。

if (new Date().getMonth() == this.monthIndex) {
 this.chooseIndex = this.day + this.firstDayIndex;
}

3.如何计算本月月历中上个月多余的天数和下个月需要加进来的天数以及日期?、

这是该日历里面比较复杂和关键的一点,我们可以看到每个月的日历总共需要42天,除开本月天数,肯定还会包括上个月部分日期和下个月部分日期,所以该问题涉及以下多个因素:

       1).本月1号前应该留给上个月多少天数

       2).上个月最后的日期是不一样的,有28 29 30 31

       3).本月的天数和留给下个月的天数

       4).非本月的日期需要置灰

这四个问题可以分别用下面的思路来解决:

问题1:计算本月的1号是周几,如果是周一那么前面应当留1天给上个月(日历从周日开始计算),如果是周二就应当留2天

每月1号可以用以下函数求得

new Date(year + '/' + monthIndex + '/' + '01').getDay();

问题2:可以在data里面建立一个hash表----monthLastDay(js对象),对应出每个月的天数,那么上个月的最后一天的日期就可以用monthLastDay[monthIndex - 1]求得,其中如果上个月是二月份要单独判断是否为闰年

monthLastDay:{
 0:31,
 1:28,
 2:31,
 3:30,
 4:31,
 5:30,
 6:31,
 7:31,
 8:30,
 9:31,
 10:30,
 11:31
},
getMonthLastDay (year, month){
 if (month != 1) {
 return this.monthLastDay[month];
 } else {
    //this.leapyear是布尔值 它表示该年是否为闰年
 if (this.leapyear) {
  return 29;
 } else {
  return 28;
 }
 }
},

得到上个月最后一天的日期以及本月1号为周几之后我们就可以知道需要填入的上个月日期有哪些了,可以往days数组(本月日历渲染数据存储数组)里push了。

问题3:这个问题就简单很多了,因为本月日历一共有42天,我们在一个i<42的for循环里面对数组days进行push,在push完上月日期和本月日期之后,把日期重置为1,继续push到for循环结束就好了

//index为上个月最后一天的日期 lastDayNum为上个月剩余天数
generateDays (index, lastDayNum) {
 let temp = 1;
 //这个for循环是push上个月的剩余日期,
 for (let i = lastDayNum; i > 0; i--) {
  this.days.push([(index - i + 1).toString()]);
 }
    //index置1,开始push本月天数
 index = 1;
 for (let i = 0; i < 42 - lastDayNum; i++) {
  //闰年二月
  if (this.leapyear) {
  if (index <= 29) {
   this.days.push(index.toString());
  }
  //非闰年月份
  } else if (index <= this.monthLastDay[this.monthIndex]) {
   this.days.push(index.toString());
   //这个else是push下个月的日期
  } else {
   this.days.push([temp.toString()]);
   temp++;
  }
  index++;
  }
 },

问题4:在上面代码中可以看到,在push非本月日期的时候,push进day数组的不是字符串而是一个数组[xxx.toString],这样就可以区分本月和非本月日期,然后在v-if里面对值进行判断添加class即可

<div v-for="(item, index) in days" :key='index' 
class="dayIndex" @click='choose(index)' 
:class="{choose: chooseIndex == index}">
  //item为string 为本月日期
 <div v-if="typeof(item) == 'string'">
 {{item}}
 </div>
  //否则为非本月日期 添加class setGrey
 <div v-else class="setGrey">
 {{item[0]}}
 </div>
</div>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript OOP类与继承
Nov 15 Javascript
用js做一个小游戏平台 (一)
Dec 29 Javascript
jQuery代码优化 事件委托篇
Nov 01 Javascript
邮箱下拉自动填充选择示例代码附图
Apr 03 Javascript
javascript的switch用法注意事项分析
Feb 02 Javascript
Javascript中的call()方法介绍
Mar 15 Javascript
C++中的string类的用法小结
Aug 07 Javascript
理解 JavaScript Scoping &amp; Hoisting(二)
Nov 18 Javascript
js 右侧浮动层效果实现代码(跟随滚动)
Nov 22 Javascript
详解vue-router 命名路由和命名视图
Jun 01 Javascript
vue中解决拖拽改变存在iframe的div大小时卡顿问题
Jul 22 Javascript
vue数据字典取键值项目的字典问题
Apr 12 Vue.js
微信小程序入口场景的问题集合与相关解决方法
Jun 26 #Javascript
Vue组件实现触底判断
Jun 26 #Javascript
vue-week-picker实现支持按周切换的日历
Jun 26 #Javascript
CKeditor4 字体颜色功能配置方法教程
Jun 26 #Javascript
Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示
Jun 26 #Javascript
ES6 Symbol数据类型的应用实例分析
Jun 26 #Javascript
亲自动手实现vue日历控件
Jun 26 #Javascript
You might like
php数组函数序列之prev() - 移动数组内部指针到上一个元素的位置,并返回该元素值
2011/10/31 PHP
php中实现记住密码下次自动登录的例子
2014/11/06 PHP
php使用function_exists判断函数可用的方法
2014/11/19 PHP
深入解析WordPress中加载模板的get_template_part函数
2016/01/11 PHP
thinkPHP模板中函数的使用方法示例
2016/11/30 PHP
php封装一个异常的处理类
2017/06/08 PHP
PHP微信模板消息操作示例
2017/06/29 PHP
让广告代码不再影响你的网页加载速度
2006/07/07 Javascript
使用JavaScript实现网页版Pongo设计思路及源代码分享
2014/06/16 Javascript
限制上传文件大小和格式的jQuery插件实例
2015/01/24 Javascript
ES6通过babel转码使用webpack使用import关键字
2016/12/13 Javascript
JavaScript 过滤关键字
2017/03/20 Javascript
理解 javascript 中的函数表达式与函数声明
2017/07/07 Javascript
JavaScript 通过Ajax 动态加载CheckBox复选框
2017/08/31 Javascript
常用的9个JavaScript图表库详解
2017/12/19 Javascript
vue axios数据请求get、post方法及实例详解
2018/09/11 Javascript
react项目如何使用iconfont的方法步骤
2019/03/13 Javascript
layer实现弹出层自动调节位置
2019/09/05 Javascript
使用 js 简单的实现 bind、call 、aplly代码实例
2019/09/07 Javascript
在Python中使用PIL模块处理图像的教程
2015/04/29 Python
浅谈Python 集合(set)类型的操作——并交差
2016/06/30 Python
详解python的四种内置数据结构
2019/03/19 Python
Python 合并多个TXT文件并统计词频的实现
2019/08/23 Python
python实现126邮箱发送邮件
2020/05/20 Python
python Tornado框架的使用示例
2020/10/19 Python
Django-celery-beat动态添加周期性任务实现过程解析
2020/11/26 Python
html5 canvas绘制放射性渐变色效果
2018/01/04 HTML / CSS
Nike加拿大官网:Nike.com (CA)
2019/04/09 全球购物
澳大利亚网上书店:QBD
2021/01/09 全球购物
《天安门广场》教学反思
2014/04/23 职场文书
国土资源局开展党的群众路线教育实践活动整改措施
2014/09/26 职场文书
班子群众路线教育实践个人对照检查材料思想汇报
2014/09/30 职场文书
《童年》读后感(三篇)
2019/08/27 职场文书
Python天气语音播报小助手
2021/09/25 Python
详解 TypeScript 枚举类型
2021/11/02 Javascript
mapstruct的用法之qualifiedByName示例详解
2022/04/06 Java/Android