徐向博 / Imin.

JS 输出日历完整篇
作者:Imin 时间:2021-04-21 分类:

封装了一个方法,记录一下,演示地址:http://blog.xuxiangbo.com/demo/calendar.html

代码如下:

html内容:

<div class="demo">
        <div class="timeBox">
            <div class="timeHead">
                <i class="erp erpweibiaoti--" @click="switchDate('py')"></i>
                <i class="erp erpzuo" @click="switchDate('pm')"></i>
                <p><span>{{head.year}}</span> 年 <span>{{head.month}}</span> 月</p>
                <i class="erp erpzuo1" @click="switchDate('nm')"></i>
                <i class="erp erpyou-" @click="switchDate('ny')"></i>
                <a>{{head.date}}号 星期{{head.day}}</a>
            </div>
            <div class="timeDay">
                <p v-for="(item, index) in weeks" v-show="index > 0" :key="index">{{item}}</p>
                <p>日</p>
            </div>
            <div class="timeDateList">
                <p
                    v-for="(item, index) in dateList" 
                    :key="index" 
                    :class="{today: item.name == '今天', hasTask: item.task, hover: currentHover == index, notCurrentMonth: item.month != 0}"
                    @click="onClick(item, index)"
                >
                    <span>{{item.name}}</span>
                </p>
            </div>
        </div>
        <div class="taskBox">
            <span class="editTask">{{task ? '编辑' : '添加'}}任务</span>
            <p>时间:{{head.year + '-' + head.month + '-' + head.date}}  <span style="margin-left: 20px;">星期{{head.day}}</span></p>
            <p>任务:{{task || '无'}}</p>
        </div>
    </div>


样式:
body{
            padding0;
            margin0;
            width100%;
            height100%;
            positionabsolute;
            displayflex;
            justify-contentcenter;
            align-itemscenter;
            backgroundrgba(0000.05);
        }
        .demo{
            width1000px;
            height580px;
            padding20px;
            backgroundrgb(255255255);
            displayflex;
            justify-contentspace-between;
            align-itemsflex-start;
        }
        .timeBox{
            width600px;
            height580px;
            border-right1px solid rgba(0000.1);
            user-selectnone;
        }
        .timeHead{
            width600px;
            height50px;
            displayflex;
            justify-contentcenter;
            align-itemscenter;
            colorrgba(0000.6);
        }
        .timeHead i{
            displayinline-block;
            padding0 3px;
        }
        .timeHead i:hover{
            colorrgb(000);
            cursorpointer;
        }
        .timeHead p span{
            displayinline-block;
            width30px;
            text-aligncenter;
            padding0 10px;
        }
        .timeHead a{
            width100px;
            positionrelative;
            left50px;
        }
        .timeDay,.timeDateList{
            width560px;
            padding0 10px;
            displayflex;
            justify-contentflex-start;
            align-contentflex-start;
            flex-wrapwrap;
        }
        .timeDay p{
            width80px;
            text-aligncenter;
            colorrgb(161161161);
            font-weightbold;
        }
        .timeDateList p{
            width80px;
            height80px;
            margin0;
            text-aligncenter;
            line-height80px;
        }
        .timeDateList p span{
            displayinline-block;
            width50px;
            height50px;
            text-aligncenter;
            line-height50px;
            border-radius100%;
            font-size14px;
            transitionall 0.3s;
            colorrgb(777777);
        }
        .timeDateList p span:hover{
            backgroundrgb(236236236);
            cursorpointer;
        }
        .timeDateList p.today span{
            colorrgb(87119224);
        }
        .timeDateList p.hasTask span{
            backgroundrgb(236236236);
        }
        .timeDateList p.hover span{
            backgroundrgb(156177247);
            colorrgb(255255255);
        }
        .timeDateList p.notCurrentMonth span{
            colorrgb(204204204);
        }
        .taskBox{
            width339px;
            height520px;
            font-size14px;
            colorrgb(161161161);
            padding30px;
            positionrelative;
        }
        .taskBox .editTask{
            positionabsolute;
            top45px;
            right20px;
            colorrgb(101131228);
            cursorpointer;
            user-selectnone;
        }
        .taskBox .editTask:hover{
            colorrgb(142167248);
        }


js:vue.js
const APP = new Vue({
            el: '.demo',
            data (){
                return {
                    weeks: ['日','一''二''三''四''五''六'],
                    dateList: [],
                    head: { year: '', month: '', date: '', day: '' },
                    currentHover: -1,
                    task: '',
                }
            },
            mounted (){
                let that = this;
                that.draw();
            },
            methods: {
                onClick (itemindex){ // 切换日期
                    let that = this;
                    if(that.currentHover == indexreturn;
                    that.currentHover = index;
                    that.head = {
                        year: item.date.substr(0,4),
                        month: Number(item.date.substr(4,2)),
                        date: Number(item.date.substr(6,2)),
                        day: that.weeks[new Date(item.date.substr(0,4+ '-' + item.date.substr(4,2+ '-' + item.date.substr(6,2)).getDay()]
                    }
                    that.task = item.task;

                    // 点击到上个月或者下个月的日期
                    if(item.month != 0){
                        that.draw(that.head.year + '-' + that.head.month + '-' + that.head.date);
                    }
                },
                switchDate (type){
                    let that = this;
                    switch (type){
                        case 'py'// 上一年
                            that.draw((that.head.year - 1+ '-' + that.head.month + '-' + that.head.date);
                        break;
                        case 'pm'// 上一月
                            if(that.head.month == 1that.draw((that.head.year - 1+ '-12-' + that.head.date);
                            else that.draw(that.head.year + '-' + (that.head.month - 1+ '-' + that.head.date);
                        break;
                        case 'nm'// 下一月
                            if(that.head.month == 12that.draw((that.head.year + 1+ '-01-' + that.head.date);
                            else that.draw(that.head.year + '-' + (that.head.month + 1+ '-' + that.head.date);
                        break;
                        case 'ny'// 下一年
                            that.draw((that.head.year + 1+ '-' + that.head.month + '-' + that.head.date);
                        break;
                        defaultbreak;
                    }
                },
                draw (time){ // 渲染日历
                    let that = this;
                    let result = [];

                    // 定义全局日期对象
                    let date = time ? new Date(time: new Date();

                    // 获取当前日期
                    that.head = {
                        year: date.getFullYear(),
                        month: date.getMonth() + 1,
                        date: date.getDate(),
                        day: that.weeks[date.getDay()]
                    }

                    // 用到的方法
                    const timeFix = t => t > 9 ? String(t: '0' + t// month、day数字小于10的时候,前面补0
                    const monthLength = month => { // 当月有多少天,输入年月的数字,如:202104
                        let num = 0;
                        let y = Number(month.substr(0,4));
                        let m = Number(month.substr(4,2));
                        if([1,3,5,7,8,10,12].indexOf(m> -1num = 31;
                        else if(m == 2){
                            // 判定闰年:能被4整除且不能被100整除,或者能被400整除的为闰年
                            if(y % 4 == 0 && y % 100 != 0 || y % 400 == 0num = 29;
                            else num = 28;
                        } else num = 30;
                        return num;
                    }

                    // 准备数据
                    // 计算本月1号是星期几
                    let day = new Date(date.getFullYear() + '-' + (date.getMonth() + 1+ '-01').getDay();

                    // 计算上月最后一天是几号(当月的天数)
                    let preMonthLength = monthLength(that.head.year + timeFix(that.head.month - 1));

                    // 用上月的末尾几天,补全当月前几天的空缺
                    for(let i = preMonthLengthi > preMonthLength - day + 1i--){
                        let object = { 
                            date: that.head.year + timeFix(that.head.month - 1+ timeFix(i), // 当前日期的输出格式:20210422
                            month: -1// 当前日期所在月份,-1 = 上月,0 = 当月,1 = 下月
                            name: i // 当前日期显示的内容
                        }
                        result.push(object);
                    }
                    result.reverse();

                    // 输出本月的列表
                    for(let i = 1i <= monthLength(that.head.year + timeFix(that.head.month)); i++){
                        let object = { 
                            date: that.head.year + timeFix(that.head.month+ timeFix(i), // 当前日期的输出格式:20210422
                            month: 0// 当前日期所在月份,-1 = 上月,0 = 当月,1 = 下月
                            name: i // 当前日期显示的内容
                        }

                        // 如果是今天,name 显示为 今天
                        let now = new Date();
                        if(object.date == now.getFullYear() + timeFix((now.getMonth() + 1)) + timeFix(now.getDate())) object.name = '今天';

                        result.push(object);
                    }

                    // 剩余的空白内容,使用下月的日期补全
                    // 日历一共显示 6 * 7 = 42天
                    // 43 - 已经有的天数 = 需要补全的天数
                    let num = 43 - result.length; // 要提前计算好剩余天数,再循环,不能把此变量放到for代码块里,否则会少渲染一天!
                    for(let i = 1i < numi++){
                        let object = { 
                            date: that.head.year + timeFix(that.head.month + 1+ timeFix(i), // 当前日期的输出格式:20210422
                            month: 1// 当前日期所在月份,-1 = 上月,0 = 当月,1 = 下月
                            name: i // 当前日期显示的内容
                        }
                        result.push(object);
                    }

                    // 绑定任务到日历,在此之前先获取到 tasklist
                    let taskList = [
                        { date: '20210501', task: '放羊' },
                        { date: '20210601', task: '杀鸡' },
                        { date: '20210701', task: '喂猪' },
                        { date: '20210801', task: '放牛' },
                        { date: '20210901', task: '割草' },
                        { date: '20211001', task: '去赛博坦进货' },
                        { date: '20211101', task: '扫荡M78星云' },
                        { date: '20211201', task: '火星一日游' },
                        { date: '20220101', task: '奔月找嫦娥约会' },
                        { date: '20220201', task: '杀鸡' },
                        { date: '20220301', task: '练习两年半' },
                    ]
                    result = result.map(item => {
                        taskList.map(task => {
                            if(task.date == item.dateitem.task = task.task;
                        })
                        return item;
                    })
                    
                    // 输出数据
                    that.dateList = result;

                    // 获取今天
                    result.map((itemindex=> {
                        if(item.date == that.head.year + timeFix(that.head.month+ timeFix(that.head.date)){
                            that.currentHover = index;
                            that.task = result[index].task;
                        }
                    })
                }
            }
        })

电商设计书籍: 认真进行了学习。 2021-07-13 17:19