Vue组件-日历功能实现

354 阅读1分钟

简单介绍一下这个组件,自动生成上个月的日历,对应日期和星期,并且给需要的日期添加点击事件。

okk 直接上代码:
因为写的是移动端,像素单位用的是rem,1rem = 75px;

<template>
    <div class="calendar-container">
        <div class="c-header">
            <div class="c-h-left">
                <span></span>
                <div class="time">{{lastMonth}}</div>
            </div>
            <div class="c-h-right">
                <div class="top">日历</div>
                <div class="month_en">{{monthEn}}</div>
            </div>
        </div>
        <div class="c-center">
            <div class="c-c-header">
                <div v-for="(item, index) in headerList" :key="index" :class="{'c-weekend-item':index > 4}" class="c-h-item">{{item}}</div>
            </div>
            <div class="c-c-body">
                <div v-for="(item, index) in bodyList" :key="index" @click="hasClick(item)?showModal(item):''" :class="{'c-weekend-item':index%7 === 6 || index%7 === 5, 'c-item-click' : hasClick(item)}" class="c-b-item">
                    <div class="item">{{item}}</div>
                    <span v-if="hasClick(item)" class="clickIcon"><span></span></span>
                </div>
            </div>
        </div>
        <div class="c-footer">
            
        </div>
    </div>
</template>

<script>
   export default {
      name: "calendar",
        data() {
         return {
            time: '2021-12-31',
            lastMonth: '2021/03',
            monthEn: 'MARCH',
            headerList: ['MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU'],
            bodyList: [],
            calendar: [
                {
                    date: "2021-04-18",
                    val: 18,
                },
                {
                    date: "2021-04-22",
                    val: 22,
                },
            ]
         }
        },
        mounted() {
           this.getData();
        },
        methods: {
           // 判断当前日期是否有点击时间
           hasClick(data) {
              let status = false;
              this.calendar.forEach((item) => {
                  if (item.val == data) {
                      status = true;
                  }
              });
              return status;
           },
           // 显示弹框
	   showModal(item) {
               console.log(item);
               // do something...
           },
           // 数据处理
           getData() {
               let dateInfo = this.getLastMonthEndTime();
                this.lastMonth = dateInfo.lastMonth;
                let i = 1;
                while (i < (dateInfo.week === 0 ? 7 : dateInfo.week)) {
                   this.bodyList.push('');
                   i++;
                }
                let j = 1;
                while (j <= dateInfo.endData) {
                   this.bodyList.push(j);
                   j++;
                }
           },
           // 获取上月结束时间/1号的星期/上月的时间
           getLastMonthEndTime() {
              let myDate = new Date();
              let year = myDate.getFullYear();
              let month = myDate.getMonth();
              if (month === 0) {
                 month = 12;
                 year = year - 1;
              } else if (month < 10) {
                 month = '0' + month;
              }
              let monthDate = new Date(year, month, 0);
              let beginTime = year + '-' + month + '-01';
              // let endTime = year + '-' + month + '-' + monthDate.getDate();
              let data = {
                 endData: monthDate.getDate(),
                 week: new Date(beginTime).getDay(),
                 lastMonth: year + '/' + month,
                };
              return data
           },
        }
   }
</script>

<style scoped lang="less">
    .calendar-container {
        width: 100%;
        height: 100%;
        border: 0.01rem solid #999999;
        border-top: 0.08rem solid #333;
        border-bottom: 0.08rem solid #333;

        .c-header {
            height: 1.5rem;
            border-bottom: .01rem solid #999999;
            overflow: hidden;
            padding: 0 0.40rem;

            .c-h-left {
                float: left;
                height: 100%;
                position: relative;

                .time {
                    height: 100%;
                    line-height: 1.5rem;
                    font-size: 0.56rem;
                    font-weight: bold;
                    font-style: italic;
                    color: #333333;
                    position: relative;
                }

                span {
                    width: 0.67rem;
                    height: 0.27rem;
                    background: rgba(202, 173, 255, 1);
                    position: absolute;
                    right: -.04rem;
                    bottom: .45rem;
                }
            }

            .c-h-right {
                float: right;
                text-align: right;
                padding-top: 0.34rem;

                .top {
                    line-height: 1;
                    font-size: 0.32rem;
                    font-weight: 400;
                    color: #333333;
                    margin-bottom: .08rem;
                }

                .month_en {
                    line-height: 1;
                    font-size: 0.43rem;
                    font-weight: bold;
                    color: #333333;
                }
            }
        }

        .c-center {
            min-height: 4.23rem;
            width: 100%;
            overflow: hidden;
            text-align: center;
            padding: 0.67rem;

            .c-c-header {
                width: 100%;
                overflow: hidden;

                .c-h-item {
                    width: 14%;
                    float: left;
                    font-size: 0.39rem;
                    font-weight: 400;
                    color: #000000;
                }
            }

            .c-c-body {
                width: 100%;
                overflow: hidden;

                .c-b-item {
                    width: 14%;
                    height: 0.67rem;
                    line-height: .67rem;
                    float: left;
                    font-size: 0.39rem;
                    font-weight: 400;
                    color: #4A4A4A;
                    margin-top: 0.20rem;
                    position: relative;

                    .item {
                        position: relative;
                        z-index: 1;
                    }

                    .clickIcon {
                        display: block;
                        width: 0.67rem;
                        height: .67rem;
                        background: #8372FF;
                        border-radius: 50%;
                        position: absolute;
                        left: 50%;
                        top: 0;
                        transform: translateX(-.33rem);
                        z-index: 0;

                        span {
                            display: block;
                            width: 0.21rem;
                            height: 0.21rem;
                            background: #B2A8FF;
                            border-radius: 50%;
                            float: right;
                            margin-top: .46rem;
                        }
                    }
                }
            }

            .c-weekend-item {
                color: #D35362!important;
            }
            
            .c-item-click {
                color: #FFFFFF!important;
            }
        }

        .c-footer {
            height: 0.88rem;
            line-height: 0.88rem;
            border-top: .01rem solid #999999;
            padding: 0 0.24rem;
            font-size: 0.32rem;
            font-weight: 400;
            color: #333333;
            overflow: hidden;
        }
    }

</style>