关于apicloud:使用APICloud-AVM框架封装app日历组件

52次阅读

共计 5335 个字符,预计需要花费 14 分钟才能阅读完成。

实现的日历效果图

话不多说,上代码!

<template>
    <view class="page">
        <safe-area></safe-area>
        <view class="calendar-wrapper">
            <view class="calendar-toolbar">
                <text class="prev" onclick="prevMonth">〈</text>
                <text class="current">{{currentDateStr}}</text>
                <text class="next" onclick="nextMonth">〉</text>
            </view>
            <view class="calendar-week">
                <text class="week-item" v-for="item of weekList" :key="item">{{item}}</text>
            </view>
            <view class="calendar-inner">
                <text class="calendar-item" v-for="(item, index) of calendarList" :key="index" :class="this.changestyle(item.disable,item.value)"
                onclick="selDate" :data-val="item.value" :data-status="item.disable" :data-num="item.date">{{item.date}}</text>
            </view>
        </view>
    </view>
</template>
<script>
    export default {
        name: 'calendar',
        installed(){this.setCurrent();
            this.calendarCreator();},
        data() {
            return{current:{},    
                weekList:['周日','周一','周二','周三','周四','周五','周六'],
                shareDate: new Date(),
                calendarList: [],
                seldate:'点击抉择日期',
                selweek:'待定',
            }
        },
        computed: {
            // 显示以后工夫
            currentDateStr() {let { year, month} = this.current;
                return `${year} 年 ${this.pad(month + 1)} 月 `;
            }
        },
        methods: {selDate (e){// console.log(JSON.stringify(e.currentTarget.dataset.val));
                let status = e.currentTarget.dataset.status;
                let num = e.currentTarget.dataset.num;
                if(status){
                    this.data.seldate = e.currentTarget.dataset.val;
                    this.getWeek();
                    if(num>7){this.prevMonth();
                    }
                    else{this.nextMonth();
                    }
                }
                else{
                    this.data.seldate = e.currentTarget.dataset.val;
                    this.getWeek();
                    // 从新加载一次日历 扭转款式
                    this.calendarCreator();}
                this.fire('clickDate', this.data.seldate);
            },
            changestyle(status,date){if(status){return 'calendar-item-disabled';}
                else{if(date == this.data.seldate){return 'calendar-item-checked';}
                    else{return 'calendar-item';}
                }
            },
            // 判断以后月有多少天
            getDaysByMonth(year, month) {// console.log("本月多少天:"+new Date(year, month + 1, 0).getDate());
                return new Date(year, month + 1, 0).getDate();},
            getFirstDayByMonths(year, month) {// console.log("本月第一天周几:"+new Date(year, month, 1).getDay());
                return new Date(year, month, 1).getDay();},
            getLastDayByMonth(year, month) {// console.log("本月最初一天周几:"+new Date(year, month + 1, 0).getDay());
                return new Date(year, month + 1, 0).getDay();},
            // 对小于 10 的数字,后面补 0
            pad(str) {return str < 10 ? `0${str}` : str;
            },
            // 点击上一月
            prevMonth() {
                this.current.month--;
                // 因为 month 的变动 会超出 0-11 的范畴,所以须要从新计算
                this.correctCurrent();
                // 生成新日期
                this.calendarCreator();},
            // 点击下一月
            nextMonth() {
                this.current.month++;
                // 因为 month 的变动 会超出 0-11 的范畴,所以须要从新计算
                this.correctCurrent();
                // 生成新日期
                this.calendarCreator();},
            // 格式化工夫,与主逻辑无关
            stringify(year, month, date) {let str = [year, this.pad(month + 1), this.pad(date)].join('-');
                return str;
            },
            // 设置或初始化 current
            setCurrent(d = new Date()) {let year = d.getFullYear();
                let month = d.getMonth();
                let date = d.getDate();
                this.current = {
                        year,
                        month,
                        date
                }
            },
            // 修改 current
            correctCurrent() {let { year, month, date} = this.data.current;
 
                let maxDate = this.getDaysByMonth(year, month);
                // 预防其余月跳转到 2 月,2 月最多只有 29 天,没有 30-31
                date = Math.min(maxDate, date);
 
                let instance = new Date(year, month, date);
                this.setCurrent(instance);
            },
            // 生成日期
            calendarCreator() {
                // 一天有多少毫秒
                const oneDayMS = 24 * 60 * 60 * 1000;
 
                let list = [];
                let {year, month} = this.data.current;
 
                // 以后月份第一天是星期几, 0-6
                let firstDay = this.getFirstDayByMonths(year, month);
                // 填充多少天                         
                let prefixDaysLen = firstDay === 0 ? 7 : firstDay;
                // 毫秒数
                let begin = new Date(year, month, 1).getTime() - oneDayMS * prefixDaysLen;
 
                // 以后月份最初一天是星期几, 0-6
                let lastDay = this.getLastDayByMonth(year, month);
                // 填充多少天,和星期的排放程序无关
                let suffixDaysLen = lastDay === 0 ? 6 : 6 - lastDay;
                // 毫秒数
                let end = new Date(year, month + 1, 0).getTime() + oneDayMS * suffixDaysLen;
 
                while (begin <= end) {
                        // 享元模式,防止反复 new Date
                        this.data.shareDate.setTime(begin);
                        let year = this.data.shareDate.getFullYear();
                        let curMonth = this.data.shareDate.getMonth();
                        let date = this.data.shareDate.getDate();
                        list.push({
                                year: year,
                                month: curMonth,
                                date: date,
                                disable: curMonth !== month,
                                value: this.stringify(year, curMonth, date)
                        });
                        begin += oneDayMS;
                }
                this.data.calendarList = list;            
                // console.log(JSON.stringify(this.data.calendarList));
            },
            // 获取选中日期的周几
            getWeek(){let index =new Date(this.data.seldate).getDay();
                let weekArr = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五','星期六'];
                let week = weekArr[index];
                this.data.selweek = week;
            },
        }
    }
</script>
<style>
    .page {height: 100%;}
    .calendar-wrapper {
        margin: 10px 10px 0 10px;
        background-color:#3c40c6;
        border-top-left-radius: 10px;
        border-top-right-radius: 10px;
        max-height: 400px;
    }
 
    .calendar-toolbar {
        padding: 10px 10px;
        flex-flow: row nowrap;
        justify-content: space-between;
        align-items: center;        
        border-bottom: 1px solid #fff;
    }
    .prev{
        flex: 1;
        text-align: center;
        color: #fff;
    }
    .current {
        flex: 1;
        text-align: center;
        color: #fff;
    }
    .next{
        flex: 1;
        text-align: center;
        color: #fff;
    }
 
    .calendar-week {
        padding: 5px 10px;
        flex-flow: row nowrap;
        justify-content: space-around;
        align-items: center;
    }
    .week-item { 
        padding: 5px;
        font-weight: bolder;
        font-size: 12px;
        color: #fff;
    }
    .calendar-inner{
        padding: 10px 10px;
        flex-flow: row wrap;
        justify-content: space-around;
        align-items: center;
    }
    .calendar-item {
        width:14%;
        font-weight: bolder;
        text-align: center;
        font-size: 15px;
        color: #fff;
        padding: 5px;
        background-color: #3c40c6;
    }
    .calendar-item-disabled {
        width:14%;
        font-weight: bolder;
        text-align: center;
        font-size: 15px;
        color: #999;
    }
    .calendar-item-checked {
        width:14%;
        font-weight: bolder;
        text-align: center;
        font-size: 15px;
        color: #000000;
        background-color: #ffffff;
        border-radius: 5px;
    }
</style>

其余页面援用

<template>
    <view class="page">
        <calendar onclickDate="getSelDate"></calendar>
        <view>
            <text> 以后日期是 </text>
            <text>{today}</text>
        </view>
    </view>
</template>
<script>
    import '../../components/calendar.stml'  
    export default {
        name: 'test',
        apiready(){},
        data() {
            return{today:''}
        },
        methods: {getSelDate(e){console.log(JSON.stringify(e));
                this.data.today = e.detail;
                api.toast({msg:'以后选中日期是:'+e.detail})
            }
        }
    }
</script>
<style>
    .page {height: 100%;}
</style>

正文完
 0