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

微信小程序日历组件 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})},//补全0zero: 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,})//初始化日历组件UIthis.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;//初始化日历组件UIthis.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;//初始化日历组件UIthis.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'})//初始化日历组件UIthis.display(this.data.year, this.data.month, this.data.date);},
复制代码

以上基本上是小程序日历组件实现的基本逻辑,介于篇幅太长还有很多实现上的细节不在此一一细说,大家可以移步我的github

微信小程序日历组件 github.com/749264345/w…

上文中有不足之处,请给出建议或更优的实现方案,谢谢~ 最后祝大家五一快乐~~

转载于:https://juejin.im/post/5cca677b51882544dc0f5b56

手把手教你写一个微信小程序日历组件相关推荐

  1. 手把手教你写个微信小程序

    手把手教你写个微信小程序 很多人看完bmob快速入门,并完成了bmob的基本配置之后依然不知道如何下手去写自己的代码,那么跟着我一起来一步一步做个小程序吧. 工具:Bmob后端云 新建小程序项目 一. ...

  2. 零基础手把手教你制作一个微信小程序云开发-实验室仪器管理系统(二)

    书接上文,我们了解到了怎么在微信开发者工具上新建一个空的云开发项目. 别急,你以为你能大展身手开始写代码了? 答案是否定的,首先你要先开始对小程序进行模块拆分 郦波老师有一句话说得很好:解决问题的最好 ...

  3. 适配mpvue平台的的微信小程序日历组件mpvue-calendar

    mpvue-calendar 基于vue-calendar的适配mpvue平台的的微信小程序日历组件 预览 安装 npm i mpvue-calendar 使用 import Calendar fro ...

  4. 微信小程序+PHP 从零写一个微信小程序

    微信小程序是越来越火,参与其中的开发者也越来越多,但是很多朋友都是只懂小程序前端开发,或者是只懂 PHP 开发,本 Chat 就是想让这部分人能够自己一个人把前后端串起来,做一个专属自己的微信小程序. ...

  5. 微信小程序傻瓜制作_微信小程序模板制作:手把手教你做一个生鲜小程序

    传统线下生鲜水果类商家如今正面临诸多问题,包括服务范围有限.客户源不稳定.缺少订单导致新鲜食材过期等等.新零售概念的提出,很多商家虽然懂得要打通线上渠道,但通常都是仅仅局限于普通O2O外卖平台,其实这 ...

  6. 手把手教你开发人工智能微信小程序(1):线性回归模型

    谈到人工智能.机器学习,我们可能会觉得很神秘,其实机器学习背后的理论并不复杂.就如同原子弹这么尖端的科技,其背后的理论就是一个很简单的公式: E = mc² 机器学习的最基础理论其实也不复杂,本文先尝 ...

  7. 写一个微信小程序,加拿大移民分数计算器

    如果你想写一个加拿大移民分数计算器的微信小程序,你需要遵循以下步骤: 首先,你需要了解如何使用微信小程序开发工具,包括如何创建小程序项目.如何编写代码和如何调试小程序. 然后,你需要了解加拿大移民分数 ...

  8. 手把手教你Nodejs获取微信小程序二维码

    [小程序二维码和普通二维码] 下图左为小程序码,右为普通二维码, 普通二维码的生成比较简单,只用jquery就可以生成,详见:https://blog.csdn.net/uikoo9/article/ ...

  9. 写一个微信小程序的代码

    微信小程序是使用小程序框架开发的,主要使用 WXML 和 WXSS 两种语言构建用户界面,使用 JavaScript 来编写逻辑. 以下是一个简单的微信小程序示例代码: <!-- index.w ...

最新文章

  1. Android之TextView文字绘制流程
  2. javafx css样式_使用CSS设置JavaFX饼图样式
  3. 三星:Android之外,技术为王
  4. 设置网页右键点击,并阻止右键点击默认事件
  5. 【C语言】(指针) 将两个数排序
  6. git 拉取 未能顺利结束 (退出码 1)_小白的 asyncio :原理、源码 到实现(1)
  7. TIOBE 11 月排行榜:Java、C、C ++、Python 和 VB .NET,谁将卫冕冠军?
  8. 台式计算机如何封存,一种计算机用声卡封存装置的制作方法
  9. SIP信令交互过程示例
  10. 计算机考试综合模块怎么做,《综合素质》几大模块备考指导要知道!
  11. 76篇 ICCV 2019 论文实现代码
  12. 3D Tiles Next
  13. 将平板电脑作为电脑显示器_平板电脑与智能显示器的比较
  14. 键盘按0键出仅计算机复制,键盘上复制粘贴按哪两个键
  15. Excel表格密码保护的解除方法
  16. 【Spring学习】Bean生命周期
  17. findbugs常见错误总结
  18. 嵌入式新闻早班车-第13期
  19. EasyCVR家庭远程视频监控解决方案
  20. 开普敦知名景点突发大火 超过20辆消防车参与救援

热门文章

  1. Nagios显示器mysql定从库: libmysqlclient.so.18: cannot open shared object file: No such
  2. 第六届省赛(软件类)真题----Java大学C组答案及解析
  3. 一个注册为输入法的木马分析
  4. python 精度损失_Python的浮点数损失精度问题
  5. 时间转换python_Python 日期与时间转换的方法
  6. ftl 展示图片_视频号变迁的内容展示逻辑
  7. dev_open linux,linux 伪终端设备 /dev/ptmx
  8. vscode怎样导入数据_【Python开发】用VSCode+Jupyter notebook 编写 Python
  9. github上的python爬虫_python爬虫入门(2):让你的github项目火起来
  10. oracle自带的sql语言环境变量,Oracle技术网—SQL*Plus系统环境变量有哪些?如何修改?...