今天咱們一塊兒寫一個微信小程序日曆組件css
微信小程序日曆組件 github.com/749264345/w…html
好,咱們先看一下要實現的模樣,以下圖 git
由以上截圖咱們能夠看到1.日曆能夠經過按鈕【切換展現效果】改變日曆的呈現效果,上圖是平鋪模式,下圖是收起滾動模式。 2.經過點擊具體的日期能夠在頁面上顯示當前選中的具體日期。 3.點擊【今天】快速回到當日視圖。 4.點擊【◀】和【▶】切換月份。 上面的四點也是基本的交互需求,咱們立刻開始。 首先,咱們先結構後樣式,作出最基本的界面結構 這邊咱們把總體結構分紅上中下,操做顯示區,星期顯示區,日期顯示區。github
<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號是星期幾。 咱們使用以下的方法:
咱們一樣在控制檯作出調試; 須要注意的是,上面的month是實際的月份,而下面這個方法須要在實際的月份上減去1。 因而咱們獲取0-6之間的值,分別對應週日~週六。 值爲6是週六,值爲0是週日。 因爲日曆的第一天是週日,週日對應的是0,因而傳入每個月1日,返回值爲多少,就是星期幾,也就說明當月1日前面空幾格。 知道了當月就幾天,當月前面有幾天,咱們作一下算法就能夠得出,當月後面有幾天,因而咱們創建以下函數:new Date(Date.UTC(year, month-1, date)).getDay();
// 組件的初始數據
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…
上文中有不足之處,請給出建議或更優的實現方案,謝謝~ 最後祝你們五一快樂~~