vue 日历组件

效果图

在这里插入图片描述

引用

<calendar @click-event="getDate" :startDate="new Date()"></calendar>

组件代码

<template>
    <div class="calendar-container">
        <div class="year">
            <div>
                <span class="fl" @click="lastYear">«</span>
                <span class="fl" @click="lastMonth">‹</span>
                <p>{{nowDate.year}}年{{nowDate.month+1}}月</p>
                <span class="fr" @click="nextYear">»</span>
                <span class="fr" @click="nextMonth">›</span>
            </div>
        </div>
        <ul class="week">
           <li v-for="(o,index) in 7" :key="o">{{formatWeek(index)}}</li> 
        </ul>
        <ul class="date">
            <li @click="clickProv" class="none-week"  v-for="o in lastMonthDays" :key="o+50" >{{lastMonthStartDay+o-1}}</li>
            <li @click="clickEvent" v-for="day in nowMonthDays" :key="day"><span :class="`${nowDate.year==onDate.year&&nowDate.month==onDate.month&&day==onDate.day?'onDate':''} ${nowDate.year==onClick.year&&nowDate.month==(onClick.month-1)&&day==onClick.day?'onClick':''}`">{{day}}</span></li>
            <li @click="clickNext" class="none-week" v-for="day in (42-lastMonthDays-nowMonthDays)" :key="day+100">{{day}}</li>
        </ul>
    </div>
</template>

<script>
export default {
    props: {
        startDate:{
           type:Date
        }
    },
    data () {
        return {
            selectDate: [],//选择日期列表
            nowDate: this.getDate(new Date()), //当前设置时间 默认为当前系统时间
            onDate:{year:this.getDate(new Date()).year,month:this.getDate(new Date()).month,day:this.getDate(new Date()).date},
            onClick:{year:this.getDate(new Date()).year,month:this.getDate(new Date()).month+1,day:this.getDate(new Date()).date}
        }
    },
    computed: {
        lastMonthDays () {
            return this.startWeek()
        },
        lastMonthStartDay () {
            return this.calcLastMonthDays(this.nowDate.year,this.nowDate.month)-(this.startWeek()-1)
        },
        nowMonthDays () {
            return this.calcDays(this.nowDate.year,this.nowDate.month)
        }
    },
    created () {
        if(this.startDate) {
            this.nowDate = this.getDate(this.startDate)
        }
    },
    methods: {
        getDate (date) {
            return {
                year: date.getFullYear(),
                month: date.getMonth(),
                day: date.getDay(),
                date: date.getDate()
            }
        },
        formatWeek (day) {
            switch (day) {                
                case 0:
                    return '日';
                case 1:
                    return '一'
                case 2:
                    return '二';
                case 3:
                    return '三'
                case 4:
                    return '四'
                case 5:
                    return '五'
                case 6:
                    return '六'
            }
        },
        //判断闰年
        isLeapYear (year) {
             return (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);
        },
        //根据日子计算星期
        calcWeekend (year,month,day) {
            return new Date(year,month,day).getDay();
        },
        //计算某年某月的天数
        calcDays (year,month) {
            const monthDay = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
            if(this.isLeapYear(year)&&month===1)
                return 29
            else 
                return monthDay[month]
        },
        //计算上个月天数
        calcLastMonthDays (year,month) {
            if(month===0) {
                return this.calcDays(year-1,11)
            }else {
                return this.calcDays(year,month-1)
            }
        },
        //上月
        lastMonth () {
            if(this.nowDate.month===0) {
                this.nowDate.month = 11
                this.nowDate.year --
            }else {
                this.nowDate.month --
            }
        },
        //下月
        nextMonth () {
            if(this.nowDate.month===11) {
                this.nowDate.month = 0
                this.nowDate.year ++
            }else {
                this.nowDate.month ++
            }
        },
        //去年
        lastYear () {
            this.nowDate.year --
        },
        //下一年
        nextYear () {
            this.nowDate.year ++
        },
        //计算当月开始星期
        startWeek () {
            return this.calcWeekend(this.nowDate.year,this.nowDate.month,1)
        },
        clickEvent (e) {
            let monthNo = this.nowDate.month;
            let month = monthNo<=11?(monthNo+1):0
            let date = {
                year:this.nowDate.year,
                month:month,
                week: new Date(this.nowDate.year,this.nowDate.month,e.target.innerText).getDay(),
                day:Number(e.target.innerText)
            }
            this.onClick = date
            this.$emit('click-event',date);
        },
        clickProv(e){
            this.lastMonth()
            this.clickEvent(e)
        },
        clickNext(e){
            this.nextMonth()
            this.clickEvent(e)
        }
    }
}
</script>


<style scoped>
    .year {
        text-align: center;
        height: 30px;
        line-height: 30px;
        background: #E0ECFF;
        font-size: 12px;
    }
    .week,.date{
        box-sizing: border-box;
        display: flex;
        flex-wrap: wrap;
        list-style: none;
    }
    .week {
        background: #F4F4F4;
        
    }
    .week li{
        height: 20px;
        line-height: 20px;
    }
    .date li{
        cursor: pointer;
        display: flex;
        justify-content: center;
        align-items: center;
        line-height: 25px;
    }
    .date li span{
        display: block;
        width: 25px;
        height: 25px;
    }
    .date li .onDate{
        color: #0000ff;
    }
    .date li .onClick{
        background: #0080cb;
        border-radius:50%;
        color: #fff;
    }
    ul>li {
        font-size: 12px;
        width: calc(100%/7);
        height: 30px;
        text-align: center;
        line-height: 30px;
        color: #333;
    }
    .none-week {
        color: #aaa;
    }
    .year>div {
        height: 30px;
        overflow: hidden;
    }
    .year span {
        line-height: 27px;
        font-size: 20px;
        display:  inline-block;
        width: 10%;
        cursor: pointer;
    }
    .year p {
        width: 50%;
        display: inline-block;
    }
    .fl {
        float: left;
    }
    .fr {
        float: right;
    }
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值