4

每天进步一点点。写个简单的小日历,依旧用vue,方便

完成图

图片描述

思路

  • 本月的天数
  • 截取上月的天数
  • 截取下月天数
  • 今天给一个样式
  • 上月、下月切换
  • 回到今天

大致需要完成的东西有以上东西

html部分

<div id="calendar">
        <div class="top">
            <div class="YM"><span class="left" @click="prevM">&lt;</span><p>{{year}}-{{month}}<span class="back" @click="backDay">今</span></p><span class="right"  @click="nextM">&gt;</span></div>
            <div class="weeks">
                <div class="week" v-for="(item,index) in weeks" :key="index">{{item}}</div>
            </div>
        </div>
        <div class="body">
            <div class="prev" v-for="(item,index) in prev">{{item}}</div>
            <div class="current" v-for="(item,index) in current" :class="isDay===index?'active':''">{{item}}</div>
            <div class="next" v-for="(item,index) in next">{{item}}</div>
        </div>
    </div>

本月天数

我主要是将日历的天数分成了3部分,创建了3个数组来保存

 data(){
    return{
        prev:[],
        current:[],
        next:[],
        year:'',
        month:'',
        weeks:['日','一','二','三','四','五','六'],
    }
},

接下来获取本月的天数

 methods:{
    currentInfo(){
        let date=new Date()
        this.year=date.getFullYear()//当年
        this.month=date.getMonth()+1//当月
        let currentDate=new Date(this.year,this.month,0)//当月最后一天
        let currentArr=[...Array(currentDate.getDate()).fill(1)]//创建当月数组,填充1
        this.current=currentArr.map((item,index)=>item+index)//做数组处理
},

当我们在创建本月数组的时候,我们只需要知道本月最后一天是多少号,便知道创建一个多少位的数组。

在获取时,有很多人使用了五花八门的方法,也有的人干脆为最后一天建立两个12位的数组,将最后一天放进去,先判断是不是闰年,再用数组取最后一天的值。

但其实new Date(Y,M,D),取D为0的时候能够取到上一月的最后一天,也无需判断是否是闰年,我偶然间发现的。有兴趣的朋友可以追根溯源去找找原因。

上月

let prevDate=new Date(this.year,this.month-1,0)//上月最后一天
let prevArr=[...Array(prevDate.getDay()+1).fill(prevDate.getDate())]//创建上月数组,填充最后一天
this.prev=prevArr.map((item,index)=>item-index).sort((a,b)=>a-b)//做数组处理

这里先是取到上月最后一天,再取星期,这样就能计算出上月需要有几位补充到当月,取当月第一天也可以。一周有7天,返回0~6的数,如果上月最后一天是星期二,看下windows的日历是补了三天,我们prevDate.getDay()得到的是2,所以为此+1,之后就是填充最后一天,用map处理一下再排序,上一个月的数据就得到了。

下月补充进来的数据毕竟简单,就不多说。完整代码如下:

currentInfo(){
        let date=new Date()
        this.year=date.getFullYear()//当年
        this.month=date.getMonth()+1//当月
        let currentDate=new Date(this.year,this.month,0)//当月最后一天
        let currentArr=[...Array(currentDate.getDate()).fill(1)]//创建当月数组,填充1
        this.current=currentArr.map((item,index)=>item+index)//做数组处理
        /*上月*/
        let prevDate=new Date(this.year,this.month-1,0)//上月最后一天
        let prevArr=[...Array(prevDate.getDay()+1).fill(prevDate.getDate())]//创建上月数组,填充最后一天
        this.prev=prevArr.map((item,index)=>item-index).sort((a,b)=>a-b)//做数组处理
        /*下月*/
        let nextArr=[...Array(6-currentDate.getDay()).fill(1)]//创建下月数组,填充1
        this.next=nextArr.map((item,index)=>item+index)
    },  

这样一个日历的主要部分就完成了,和windows下的日历对比下,一模一样就说明没错

上月和下月按钮

想要获取上月的日历,其实就是重新运行了currentInfo()函数,只是月份取得上月,那很简单,传参

currentInfo(year,month){
        let date=new Date()
        this.year=year||date.getFullYear()//当年
        this.month=month||date.getMonth()+1//当月
        let currentDate=new Date(this.year,this.month,0)//当月最后一天
        let currentArr=[...Array(currentDate.getDate()).fill(1)]//创建当月数组,填充1
        this.current=currentArr.map((item,index)=>item+index)//做数组处理
        /*上月*/
        let prevDate=new Date(this.year,this.month-1,0)//上月最后一天
        let prevArr=[...Array(prevDate.getDay()+1).fill(prevDate.getDate())]//创建上月数组,填充最后一天
        this.prev=prevArr.map((item,index)=>item-index).sort((a,b)=>a-b)//做数组处理
        /*下月*/
        let nextArr=[...Array(6-currentDate.getDay()).fill(1)]//创建下月数组,填充1
        this.next=nextArr.map((item,index)=>item+index)
    }

我们将函数进行如上改造,当有年月参数传入时,就使用参数;当没有年月参数传入时,就使用系统时间的年月。之后只需要做两个按钮函数就行了

prevM(){
        let year,month
        if(this.month!==1){//不是一月,月份递减,年份不变
            month=--this.month
            year=this.year
        }else{//否则年份递减,月份变为12
            month=12
            year=--this.year
        }   
        this.currentInfo(year,month)
    },
nextM(){
        let year,month
        if(this.month!==12){
            month=++this.month
            year=this.year
        }else{
            month=1
            year=++this.year
        } 
        this.currentInfo(year,month)
    },

当天的样式

该如何加当天的样式其实有很多方法,我是先找出当天,然后和循环的index挂钩,判断是否需要加样式
先在data中加入isDay这个数据

currentDay(){
        let date=new Date()                    
        if(this.year===date.getFullYear()&&this.month===date.getMonth()+1){//如果是当年当月
            this.isDay=date.getDate()-1//获取到今天的号数,因为index是从0循环,所以这里-1
        }else{
            this.isDay=''
        }
    },

之后就是通过vue绑定样式,当(今天-1)=index,即:class="isDay===index?'active':''"给此添加一个active样式

回到今天

backDay(){                   
    this.currentInfo()
    this.currentDay()
}

最后

 mounted(){
    this.currentInfo()
    this.currentDay()
}

利用生命周期函数进行初始化(这个应该一开始就做)

源码

https://github.com/yuyeqianxu...
希望能帮助到和我一样的小白朋友们,有bug麻烦反馈,谢谢!


羽叶千寻
133 声望6 粉丝