Vue实现日历小插件

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

先看下效果图吧, 如下

源码可见于我的github

实现关键点:

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>

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

(0)

相关推荐

  • 亲自动手实现vue日历控件

    之前项目中有用到日历控件,当时由于时间问题,是在网上找到一个demo,然后二次开发的,从那时就想着自己写一个日历控件.这篇文章说明日历数据的处理,去除月份天数判断以及是否闰年判断. 设计(以最常用的按月份的日历) 日历其实大家都很熟悉,一切的设计都是从功能出发,这是根本.日历的功能分为两大块. 日历头部:当前年份/月份. 日历主体:当前月份的具体的日期信息. 日历主体的行数:现在我们看到的日历基本上为6行,因为一个月最多为31天,假设当前月的第一天为上一月最后一周的最后一天.如果是五行数据的话则

  • 基于Vue实现支持按周切换的日历

    基于Vue的日历小功能,可根据实际开发情况按每年.每月.每周.进行切换,具体内容如下 <template> <div class="date"> <!-- 年份 月份 --> <div class="month"> <p>{{ currentYear }}年{{ currentMonth }}月</p> </div> <!-- 星期 --> <ul class=&q

  • VUE实现日历组件功能

    哈哈, 就在昨天笔者刚刚在Github 上发布了一个基于VUE的日历组件.过去做日历都是需要引用 jquery moment 引用 fullCalendar.js 的.几者加起来体积庞大不说,也并不是很好使用在vue这种数据驱动的项目里.所以笔者经过一周的拍脑袋,做了一个十分简陋的版本. 简介 目前只支持月视图,该组件是 .vue 文件的形式.所以,大家在使用的时候 是需要node的咯~~~ 安装 npm install vue-fullcalendar DEMO 针对这个组件, 本人做了一个十

  • vue实现一个炫酷的日历组件

    公司业务新开了一个商家管理微信H5移动端项目,日历控件是商家管理员查看通过日程来筛选获取某日用户的订单等数据. 如图: 假设今天为2018-09-02 90天前: 90天后; 产品需求: 展示当前日期(服务器时间)前后90天,一共181天的日期. 日历可以左右滑动切换月份. 当月份的如果不在181天区间的,需要置灰并且不可点击. 点击日历绑定的节点的外部,关闭弹窗. 涉及内容: 获取服务器时间,渲染日历数据 vue-touch监听手势滑动事件 ios日期兼容处理 clickOutSide自定义指

  • vue实现日历备忘录功能

    用vue写了个日历备忘录的功能,省略了备忘录的增删改查功能. 直接上代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>备忘录</title> <style type="text/css"> #box{ width: 469px; } /*日历*/ *{ padding:

  • Vue 组件(component)教程之实现精美的日历方法示例

    组件(component)是Vue最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码,根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己的需要,使用不同的组件来拼接页面.这种开发模式使得前端页面易于扩展,且灵活性高,而且组件之间也实现了解耦. 最近应公司的要求,需要开发一个精美的日历组件(IOS , 安卓, PC 的IE9+都能运行),写完后想把它分享出来,希望大家批评. 先来个截图 代码已经分享到 https://github.com/zhangKun

  • vue实现简单的日历效果

    最近在项目中遇到了一个需求,在vue中创建一个组件,这个组件显示的是当前的日期,以及在当前的日需要处理的事项,处理的事项的信息会以后端的接口的形式返回. 需求确认后,搭建了一下,在这里记录了一下,现在是简单的实现了这个需求,但是肯定的是后期需要进行修改. vue就不多说了,在vue中使用的是原生JS 效果图(基本没有样式,很low) 现在实现的都是最初级的版本,代码里面的容错,还有一些性能上的处理,并没有书写. 不多说,上代码: 首先是vue的html结构,很简单,里面添加了一些其他时间形式的显

  • 基于Vue2-Calendar改进的日历组件(含中文使用说明)

    一,前言 我是刚学Vue的菜鸟,在使用过程中需要用到日历控件,由于项目中原来是用jQuery写的,因此用了bootstarp的日历控件,但是配合Vue实在有点蛋疼,不够优雅-- 于是网上搜了好久找到了Vue2-Calendar,不用说,挺好用的,但是同时也发现这个组件有些问题,有些功能挺不符合我们的要求,于是着手改了一版 二,改进的功能 在Vue2-Calendar v2.2.4 版基础上作了优化. 1.改进原控件无法切换语言的BUG,支持 lang='zh-CN'和'en'. 2.日历面板增加

  • Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示

    之前写了一篇周和月日历,但感觉体验不是太好,所以有重新做了一遍,加上了动画.还可以自定义显示日历里的内容. 现在贴出项目源码,我现在是放在CSDN里的下载资源,这里哦 现在我上传带了GitHub上了,可以去这里下载哦,如果觉得好的话希望能给个star,谢谢支持 1.总共分为两个组件(父组件calendar.vue) <template> <div class="calendar-box"> <ul class="calendar-head&quo

  • Vue.js创建Calendar日历效果

    使用 Vue.js 进行数据与视图的绑定,数据更新会让视图自动进行更新,类似 Android 里面的 DataBinding. 实现一个HTML的日历效果. html 部分 <div id="calendar"> <!-- 年份 月份 --> <div class="month"> <ul> <li class="arrow" @click="pickPre(currentYear,

随机推荐