手把手教你写一个微信小程序日历组件
栏目: 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建立日历
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Designing Data-Intensive Applications
Martin Kleppmann / O'Reilly Media / 2017-4-2 / USD 44.99
Data is at the center of many challenges in system design today. Difficult issues need to be figured out, such as scalability, consistency, reliability, efficiency, and maintainability. In addition, w......一起来看看 《Designing Data-Intensive Applications》 这本书的介绍吧!