python日历程序编写_手把手教你写一个微信小程序日历组件

今天我们一起写一个微信小程序日历组件

好,我们先看一下要实现的模样,如下图

1460000019056318

1460000019056319

由以上截图我们可以看到

1.日历可以通过按钮【切换展示效果】改变日历的呈现效果,上图是平铺模式,下图是收起滚动模式。

2.通过点击具体的日期可以在页面上显示当前选中的具体日期。

3.点击【今天】快速回到当日视图。

4.点击【◀】和【▶】切换月份。

上面的四点也是基本的交互需求,我们马上开始。

首先,我们先结构后样式,做出最基本的界面结构

这边我们把整体结构分成上中下,操作显示区,星期显示区,日期显示区。

{{lastMonth}}

{{title}}

{{nextMonth}}

今天

{{item}}

{{item}}

{{item.date}}

{{item}}

这是我们基本的日历结构,机智的小伙伴已经从布局中知道我们实现的大致逻辑了,是的,我们先获取当月有多少天,上月和下月有多少天,这样我们的日历就出来了。好,慢慢来,下面我们详细说,我们先写上基本的样式。

.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的代码。

{{item}}

这样我们就能看到我们想要的效果。

1460000019056320

下面我们开始日期的显示,我们先获取当月有几天,这里的核心代码是

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

由此我们做如下尝试

1460000019056321

我们如期获得了返回值,而当我们传入日期为0时返回了31为当月的全部天数。

由于JavaScript中day的范围为1~31中的值,所以当设为0时,会向前 一天,也即表示上个月的最后一天,通过这种方式可以得到每个月份的天数。

知道了获取当月天数的原理,我们还需要知道当月1号是星期几。

我们使用如下的方法:

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

![http://www.w3school.com.cn

](https://upload-images.jianshu...

我们同样在控制台做出调试;

1460000019056322

需要注意的是,上面的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代码,同时我们为上月,下月,今天,三个按钮添加相关事件监听。

{{lastMonth}}

{{title}}

{{nextMonth}}

今天

{{item}}

{{item.date}}

{{item}}

相关的事件监听:

//默认选中当天 并初始化组件

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函数中我们添加事件监听函数,将选中的日期发送到页面,我们通过事件订阅来获取的相关值。

//组件监听事件

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

上文中有不足之处,请给出建议或更优的实现方案,谢谢~

最后祝大家五一快乐~~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值