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中难以理解的11个问题
Dec 09 Javascript
jQuery中[attribute*=value]选择器用法实例
Dec 31 Javascript
异步JS框架的作用以及实现方法
Oct 29 Javascript
JavaScript中数组添加值和访问值常见问题
Feb 06 Javascript
jQuery中$.each()函数的用法引申实例
May 12 Javascript
用JavaScript获取页面文档内容的实现代码
Jun 10 Javascript
js绘制购物车抛物线动画
Nov 18 Javascript
vue2.0 常用的 UI 库实例讲解
Dec 12 Javascript
Angular实现点击按钮后在上方显示输入内容的方法
Dec 27 Javascript
微信小程序使用map组件实现解析经纬度功能示例
Jan 22 Javascript
JavaScript闭包相关知识解析
Oct 19 Javascript
JavaScript中10个Reduce常用场景技巧
Jun 21 Javascript
微信小程序入口场景的问题集合与相关解决方法
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编写PDF文档生成器
2006/10/09 PHP
PHP实现求解最长公共子串问题的方法
2017/11/17 PHP
PHP从零开始打造自己的MVC框架之路由类实现方法分析
2019/06/03 PHP
javascript语句中的CDATA标签的意义
2007/05/09 Javascript
html向js方法传递参数具体实现
2013/08/08 Javascript
node.js适合游戏后台开发吗?
2014/09/03 Javascript
jquery实现鼠标滑过小图查看大图的方法
2015/07/20 Javascript
JS+CSS实现闪烁字体效果代码
2016/04/05 Javascript
js格式化时间的简单实例
2016/11/27 Javascript
AngularJS Controller作用域
2017/01/09 Javascript
浅谈js中startsWith 函数不能在任何浏览器兼容的问题
2017/03/01 Javascript
很棒的vue弹窗组件
2017/05/24 Javascript
jquery引入外部CDN 加载失败则引入本地jq库
2018/05/23 jQuery
Angular 实现输入框中显示文章标签的实例代码
2018/11/07 Javascript
3分钟读懂移动端rem使用方法(推荐)
2019/05/06 Javascript
[02:00]DOTA2英雄COSPLAY闹市街头巡游助威2015国际邀请赛
2015/08/02 DOTA
python使用matplotlib绘制折线图教程
2017/02/08 Python
python扫描proxy并获取可用代理ip的实例
2017/08/07 Python
实例讲解Python爬取网页数据
2018/07/08 Python
使用selenium模拟登录解决滑块验证问题的实现
2019/05/10 Python
使用Keras实现简单线性回归模型操作
2020/06/12 Python
Python建造者模式案例运行原理解析
2020/06/29 Python
python 密码学示例——凯撒密码的实现
2020/09/21 Python
python中K-means算法基础知识点
2021/01/25 Python
深入理解HTML5定时器requestAnimationFrame的使用
2018/12/12 HTML / CSS
美国在线轮胎零售商:SimpleTire
2019/04/08 全球购物
揭牌仪式策划方案
2014/05/28 职场文书
运动会宣传口号
2014/06/09 职场文书
2014年国庆标语
2014/06/30 职场文书
海上钢琴师的观后感
2015/06/11 职场文书
2016消防宣传标语口号
2015/12/26 职场文书
私人贷款担保书该怎么写呢?
2019/07/02 职场文书
JavaWeb 入门:Hello Servlet
2021/07/16 Java/Android
python实现会员信息管理系统(List)
2022/03/18 Python
《雀魂PONG☆》4月1日播出 PV角色设定情报
2022/03/20 日漫
IDEA 2022 Translation 未知错误 翻译文档失败
2022/04/24 Java/Android