手把手教你写一个微信小程序日历组件
栏目: JavaScript · 发布时间: 5年前
内容简介:今天我们一起写一个微信小程序日历组件好,我们先看一下要实现的模样,如下图
今天我们一起写一个微信小程序日历组件
微信小程序日历组件
https://github.com/749264345/wx-calendar好,我们先看一下要实现的模样,如下图
由以上截图我们可以看到
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();
]( https://upload-images.jianshu...
由此我们做如下尝试
我们如期获得了返回值,而当我们传入日期为0时返回了31为当月的全部天数。
由于JavaScript中day的范围为1~31中的值,所以当设为0时,会向前 一天,也即表示上个月的最后一天,通过这种方式可以得到每个月份的天数。
知道了获取当月天数的原理,我们还需要知道当月1号是星期几。
我们使用如下的方法:
new Date(Date.UTC(year, month-1, date)).getDay();
]( https://upload-images.jianshu...
我们同样在控制台做出调试;
需要注意的是,上面的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
微信小程序日历组件
https://github.com/749264345/wx-calendar上文中有不足之处,请给出建议或更优的实现方案,谢谢~
最后祝大家五一快乐~~
以上所述就是小编给大家介绍的《手把手教你写一个微信小程序日历组件》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- vue日历组件
- 可视化搭建平台的地图组件和日历组件方案选型
- vue写一个炫酷的日历组件
- React 组件库 uiw 1.5.5 发布,日历插件增强
- 原生JavaScript实现造日历轮子
- 第二章 使用VUX建立日历
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
电脑报(上下册)
电脑报社 / 西南师范大学出版社 / 2006-12-01 / 45.00元
全套上、下两册,浓缩2006年电脑报精华文章。附录包含70余篇简明IT应用指南,覆盖软件、硬盘、数码、网络四大领域。配赠权威实用的2006-2007中国计算机年鉴DVD光盘,近1.4GB海量信息与资源超值奉献。8大正版超值软件,涵盖系统维护、系统安全、办公应用、多媒体娱乐等四大领域。微软、腾讯、友立等知名厂商,新年献礼。提供2006-2007全系列硬件、数码产品资讯,兼具知识性与资料性。官方网站全......一起来看看 《电脑报(上下册)》 这本书的介绍吧!
UNIX 时间戳转换
UNIX 时间戳转换
正则表达式在线测试
正则表达式在线测试