用戶
 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

掃一掃,登錄網站

小程序社區 首頁 教程 查看內容

:手把手教你寫一個微信小程序日歷組件

巴黎彩票计划 www.hknsi.icu Rolan 2019-5-6 00:24

今天我們一起寫一個微信小程序日歷組件 微信小程序日歷組件 github.com/749264345/w… 好,我們先看一下要實現的模樣,如下圖 由以上截圖我們可以看到 1.日歷可以通過按鈕【切換展示效果】改變日歷的呈現效果, ...

今天我們一起寫一個微信巴黎彩票计划日歷組件

微信小程序日歷組件 github.com/749264345/w…

好,我們先看一下要實現的模樣,如下圖

由以上截圖我們可以看到

1.日歷可以通過按鈕【切換展示效果】改變日歷的呈現效果,上圖是平鋪模式,下圖是收起滾動模式。 2.通過點擊具體的日期可以在頁面上顯示當前選中的具體日期。 3.點擊【今天】快速回到當日視圖。 4.點擊【?】和【?】切換月份。 上面的四點也是基本的交互需求,我們馬上開始。 首先,我們先結構后樣式,做出最基本的界面結構 這邊我們把整體結構分成上中下,操作顯示區,星期顯示區,日期顯示區。

<view class='calendar'>
    <!--顯示當前年月日-->
    <view class='calendar-title'>
        <view class='item ctrl' bindtap='lastMonth'>{{lastMonth}}</view>
        <view class='item title'>{{title}}</view>
        <view class='item ctrl' bindtap='nextMonth'>{{nextMonth}}</view>
        <view class='item ctrl today' bindtap='today'>今天</view>
    </view>

    <!--星期-->
    <view class='calendar-week'>
        <view class='item'>{{item}}</view>
    </view>

    <!--日期-->
    <view class='calendar-container'>
        <!--上個月占位格子-->
        <view class='grid gray'>{{item}}</view>

        <!--當月格子-->
        <view class='grid'>
            <view class="wrap">{{item.date}}</view>
        </view>

        <!--下個月占位格子-->
        <view class='grid gray'>{{item}}</view>
    </view>
</view>
復制代碼

這是我們基本的日歷結構,機智的小伙伴已經從布局中知道我們實現的大致邏輯了,是的,我們先獲取當月有多少天,上月和下月有多少天,這樣我們的日歷就出來了。好,慢慢來,下面我們詳細說,我們先寫上基本的樣式。

.calendar {
    width: 100%;
    text-align: center;
    font-size: 30rpx;
    box-sizing: border-box;
}

/* 標題 */
.calendar-title {
    line-height: 70rpx;
    font-size: 30rpx;
    text-align: left;
    padding: 0 20rpx;
    box-sizing: border-box;
}

.calendar-title .ctrl {
    display: inline-block;
    padding: 0 20rpx;
    background: #f5f5f5;
    border-radius: 10rpx;
}

.calendar-title .item {
    display: inline-block;
    vertical-align: middle;
    line-height: 50rpx;
}

.calendar-title .title {
    min-width: 300rpx;
    text-align: center;
}

.calendar-title .today {
    float: right;
    margin-top: 10rpx;
}

/* 星期 */
.calendar-week {
    display: flex;
    text-align: center;
    padding: 20rpx 10rpx;
    box-sizing: border-box;
    border-top: 1rpx solid #e0e0e0;
    border-bottom: 1rpx solid #e0e0e0;
    background: #f5f5f5;
}

.calendar-week .item {
    flex: 1;
}

/* 日期 */
.calendar-container {
    display: flex;
    flex-wrap: wrap;
    padding: 20rpx 10rpx;
    box-sizing: border-box;
}

.calendar-container .grid {
    display: inline-block;
    width: 14.28571428571429%;
    line-height: 70rpx;
    position: relative;
    z-index: 1;
}

.calendar-container .grid.gray {
    color: #ccc;
}

.calendar-container .grid .wrap.select {
    background: rgb(49, 120, 228);
    border-radius: 10rpx;
    color: #fff;
    width: 80%;
    margin: 0 auto;
}
復制代碼

以上我們基本試下了日歷的界面,下面我們來實現星期和日期的展示。 好,我們先顯示星期,我們先在組件中定義一個數組,用來遍歷顯示星期的標題;

Component({
    properties: {
        //星期數組
        weekText: {
            type: Array,
            value: ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
        }
    },
    ...
})
復制代碼

我們將星期的標題定義為可配置的模式,默認顯示如上的文字,之后我們可以在組件外自定義,個性化顯示。于是我們調整下wxml的代碼。

    <!--遍歷星期-->
    <view class='calendar-week'>
        <view wx:for='{{weekText}}' class='item' wx:key='{{item}}'>{{item}}</view>
    </view>
復制代碼

這樣我們就能看到我們想要的效果。

下面我們開始日期的顯示,我們先獲取當月有幾天,這里的核心代碼是

new Date(year, month, date).getDate();

由此我們做如下嘗試

我們如期獲得了返回值,而當我們傳入日期為0時返回了31為當月的全部天數。

由于JavaScript中day的范圍為1~31中的值,所以當設為0時,會向前 一天,也即表示上個月的最后一天,通過這種方式可以得到每個月份的天數。

知道了獲取當月天數的原理,我們還需要知道當月1號是星期幾。 我們使用如下的方法:

new Date(Date.UTC(year, month-1, date)).getDay();

我們同樣在控制臺做出調試;

需要注意的是,上面的month是實際的月份,而下面這個方法需要在實際的月份上減去1。 于是我們獲取0-6之間的值,分別對應周日~周六。 值為6是周六,值為0是周日。 由于日歷的第一天是周日,周日對應的是0,于是傳入每月1日,返回值為多少,就是星期幾,也就說明當月1日前面空幾格。 知道了當月就幾天,當月前面有幾天,我們做一下算法就可以得出,當月后面有幾天,于是我們建立如下函數:

    // 組件的初始數據
    data: {
        //當月格子
        thisMonthDays: [],
        //上月格子
        empytGridsBefore: [],
        //下月格子
        empytGridsAfter: [],
},

methods: {
        //獲取當月天數
        getThisMonthDays: function (year, month) {
            return new Date(year, month, 0).getDate();
        },
        // 繪制當月天數占的格子
        createDays: function (year, month) {
            let thisMonthDays = [],
                days = this.getThisMonthDays(year, month);
            for (let i = 1; i <= days; i++) {
                thisMonthDays.push({
                    date: i,
                    dateFormat: this.zero(i),
                    monthFormat: this.zero(month),
                    week: this.data.weekText[new Date(Date.UTC(year, month - 1, i)).getDay()]
                });
            }
            this.setData({
                thisMonthDays
            })
        },
        //獲取當月空出的天數
        createEmptyGrids: function (year, month) {
            let week = new Date(Date.UTC(year, month - 1, 1)).getDay(),
                empytGridsBefore = [],
                empytGridsAfter = [],
                emptyDays = (week == 0 ? 7 : week);
            //當月天數
            var thisMonthDays = this.getThisMonthDays(year, month);
            //上月天數
            var preMonthDays = month - 1 < 0 
                ? this.getThisMonthDays(year - 1, 12) 
                : this.getThisMonthDays(year, month - 1);

            //空出日期
            for (let i = 1; i <= emptyDays; i++) {
                empytGridsBefore.push(preMonthDays - (emptyDays - i));
            }

            var after = (42 - thisMonthDays - emptyDays) - 7 >= 0 
                        ? (42 - thisMonthDays - emptyDays) - 7 
                        : (42 - thisMonthDays - emptyDays);
            for (let i = 1; i <= after; i++) {
                empytGridsAfter.push(i);
            }
            this.setData({
                empytGridsAfter,
                empytGridsBefore
            })
        },

        //補全0
        zero: function (i) {
            return i >= 10 ? i : '0' + i;
        },
}
復制代碼

我們同樣修改下wxml代碼,同時我們為上月,下月,今天,三個按鈕添加相關事件監聽。

    <!--顯示當前年月日-->
    <view class='calendar-title'>
        <view class='item ctrl' bindtap='lastMonth'>{{lastMonth}}</view>
        <view class='item title'>{{title}}</view>
        <view class='item ctrl' bindtap='nextMonth'>{{nextMonth}}</view>
        <view class='item ctrl today' bindtap='today'>今天</view>
    </view>
復制代碼
<!--上個月占位格子-->
<view class='grid gray' wx:for='{{empytGridsBefore}}' wx:key='{{item}}'>{{item}}</view>

<!--當月格子-->
<view class='grid' wx:for='{{thisMonthDays}}' wx:key='{{indx}}'>
   <view class='self' wx:if="{{ format === year+'-'+item.monthFormat+'-'+item.dateFormat }}"></view>
   <view class="wrap {{ select === year+'-'+item.monthFormat+'-'+item.dateFormat ? 'select' :''}}" bindtap='select' data-date='{{item.date}}'>{{item.date}}</view>
</view>

<!--下個月占位格子-->
<view class='grid gray' wx:for='{{empytGridsAfter}}' wx:key='{{item}}'>{{item}}</view>
復制代碼

相關的事件監聽:

//默認選中當天 并初始化組件
today: function () {
    let DATE = this.data.defaultValue ? new Date(this.data.defaultValue) : new Date(),
        year = DATE.getFullYear(),
        month = DATE.getMonth() + 1,
        date = DATE.getDate(),
        select = year + '-' + this.zero(month) + '-' + this.zero(date);

    this.setData({
        format: select,
        select: select,
        year: year,
        month: month,
        date: date,
        YEAR: year,
        MONTH: month,
        DATE: date,
    })

    //初始化日歷組件UI
    this.display(year, month, date);

    //發送事件監聽
    this.triggerEvent('select', select);
},
//上個月
lastMonth: function () {
    let month = this.data.month == 1 ? 12 : this.data.month - 1;
    let year = this.data.month == 1 ? this.data.year - 1 : this.data.year;
    //初始化日歷組件UI
    this.display(year, month, 0);
},
//下個月
nextMonth: function () {
    let month = this.data.month == 12 ? 1 : this.data.month + 1;
    let year = this.data.month == 12 ? this.data.year + 1 : this.data.year;
    //初始化日歷組件UI
    this.display(year, month, 0);
},
復制代碼

代碼中我們使用this.display(year, month, 0)為組件統一初始化; 同時在today函數中我們添加事件監聽函數,將選中的日期發送到頁面,我們通過事件訂閱來獲取的相關值。

<Calendar id="Calendar" bind:select="select"></Calendar>
復制代碼
//組件監聽事件
select(e) {
    this.setData({
        selectVal:e.detail
    })
},
復制代碼

最后我們為切換顯示效果的按鈕添加事件:

    toggleType(){
        this.selectComponent('#Calendar').toggleType();
    }
復制代碼

組件中對應的方法,每當切換展示效果,組件都需要初始化

        //切換展示
        toggleType(){
            this.setData({
                toggleType: this.data.toggleType == 'mini' ? 'large' :'mini'
            })
            //初始化日歷組件UI
            this.display(this.data.year, this.data.month, this.data.date);
        },
復制代碼

以上基本上是小程序日歷組件實現的基本邏輯,介于篇幅太長還有很多實現上的細節不在此一一細說,大家可以移步我的github

微信小程序日歷組件 github.com/749264345/w…

上文中有不足之處,請給出建議或更優的實現方案,謝謝~ 最后祝大家五一快樂~~

分享至 : QQ空間
收藏
原作者: 易在掘金 來自: 掘金
时时彩开彩结果查询新浪爱彩 翔龙彩票官 好彩3中奖查询 今天20选5开奖号码是多少 龙虎和时时彩走势图 36选7复式中奖计算 重庆时时开奖视频软件 湖北体彩11选五一定牛 中国体彩开奖视频直播 双色球081期历史开奖结果 辽宁省福彩十二选5走势图 江西多乐彩开奖结果 好彩3玩法技巧 赛车8码怎么做到无错 双色基本球走势300 冠亚单双大小怎么套利