vue实现封装日历组件

1,176 阅读2分钟

前端实际的开发中会面临各种页面需求,所以我们不可能永远套用那些限定的UI的模板,最近根据需求自己封装了一个日历组件。

效果图:

03ea6ca96b5d3734bf7f5e37dba0595.jpg

对于日历的实现我的逻辑是这样的:

1.首先我需要写的日历是总共展示7列*5行,就是35天的数据就够了,我总共写了一个List存35天的日期,一个月最多只有31天,所以肯定还有多余的几天需要展示上个月末或者下个月初的日期。这里把所有日期都存一个数组里面,再用方法做区分。

具体代码:

template页面:

<template>
    <div class="main">
        <div class="header">
            <a-icon type="left-circle" @click="clickReduceMonth" style="cursor: pointer"/>
            <div style="padding: 0 10px;font-size: 16px">{{ currentMonth }}月</div>
            <a-icon type="right-circle" style="cursor: pointer" @click="clickAddMonth"/>
        </div>
        <div class="table_box">
            <table class="tables">
                <tr class="tr-header">
                    <th v-for="(item,index) in weeks" :key="index">{{ item }}</th>
                </tr>
                <tr class="tr-container" v-for="index in 5" :key="index">
                    <td v-for="n in 7" :key="n" :class="{'last':isCurrentMonth(index,n)}">{{ getCalendar(index, n) }}
                    </td>
                </tr>
            </table>
        </div>
    </div>

逻辑方法: 1.首先获取这个月和上个月在日历里面占的天数

/**
 *@description 获取上个月和当前月在日历的天数
 */
getDaysOfMonth(year: any, month: any) {
    this.calendarList = [] //清空数据
    var daysCount = new Date(year, month, 0).getDate(); //这个月的天数
    var lastMonthsCount = new Date(year, month - 1, 0).getDate() //上个月的天数
    var todayWeek = new Date(year, month - 1, 1).getDay() //这个月第一天是周几
    for (let i = 0; i < todayWeek; i++) {
        const day = lastMonthsCount - i;
        this.calendarList.unshift(day)
    } //加入上个月的尾数
    this.lastMonthCount = this.calendarList.length
    setTimeout(() => {
        for (let a = 1; a <= daysCount; a++) {
            this.calendarList.push(a)
        }
        //加入这个月的日期
        this.calendarList = this.calendarList.length > 35 ? this.calendarList.slice(0, 35) : this.calendarList
    }, 300)
}

2.如果直接在页面上渲染35个日期天数,因为是双层循环所以肯定有很多日期数据重复了,并且取到错误的日期,所以我们需要写一个方法来根据循环的Index判断具体是哪一天

/**
 * @description 判断具体为日历的哪一天
 */
getCalendar(m: any, n: any) {
    const list: any = this.calendarList.slice((m - 1) * 7, (m - 1) * 7 + 7)
    return list[n - 1]
}

3.实现日历的月份切换

 * @description 判断日期是否在当月
 */
isCurrentMonth(last: any, current: any) {
    const i = (last - 1) * 7 + (current - 1)
    if (i <= this.lastMonthCount - 1) {
        return false
    }
    return true
}
clickAddMonth() {
    if (Number(this.currentMonth) == 12) {
        return
    }
    this.currentMonth = Number(this.currentMonth) + 1;
    const year = new Date().getFullYear()
    this.getDaysOfMonth(year, this.currentMonth)
}

clickReduceMonth() {
    if (Number(this.currentMonth) == 1) {
        return
    }
    this.currentMonth = Number(this.currentMonth) - 1;
    const year = new Date().getFullYear()
    this.getDaysOfMonth(year, this.currentMonth)
}

主要的Less代码:

table tr {
    text-align: center;
}

table td,
table th {
    border-right: 1px solid rgba(122, 180, 210, 0.4);
    /*设置表格单元格外边框,只设置右下边框*/
    border-bottom: 1px solid rgba(122, 180, 210, 0.4);
    padding: 10px;
    /*设置单元格内边距,单元格内容显得不拥挤*/
    text-align: center;
}

tr:last-child td:first-child {

}

tr:last-child td:last-child {
    border-bottom: none;
}

tr:last-child td {
    border-bottom: none;
}

tr td:last-child, tr th:last-child {
    border-right: none;
}

tr:nth-child(even) {
}