好用的微信小程序日历组件(可滑动,可展开收缩,可标点)

  • 好用的微信小程序日历组件(可滑动,可展开收缩,可标点)已关闭评论
  • 209 次浏览
  • A+
所属分类:Web前端
摘要

原生小程序编写,简单轻便,拿来即用。
gitee地址:https://gitee.com/qq_connect-EC6BCC0B556624342/wx-calendar


效果图

好用的微信小程序日历组件(可滑动,可展开收缩,可标点)

组件介绍

原生小程序编写,简单轻便,拿来即用。
gitee地址:https://gitee.com/qq_connect-EC6BCC0B556624342/wx-calendar

代码部分(这里可能不是最新的推荐去gitee克隆代码)

calendar.wxml

<!--component/calendar/calendar.wxml--> <view class="calendar">     <view class="title">         <view class="header-wrap">             <view class="flex">                 <view class="title">{{title}}</view>                 <view class="month">                     <block wx:if="{{title}}">                         (                     </block>                     {{selectDay.year}}年{{selectDay.month}}月                     <block wx:if="{{title}}">                         )                     </block>                 </view>             </view>             <block wx:if="{{goNow}}">                 <view wx:if="{{open && !(nowDay.year==selectDay.year&&nowDay.month==selectDay.month&&nowDay.day==selectDay.day)}}" class="today" bindtap="switchNowDate">                     今日                 </view>             </block>         </view>      </view>      <!-- 日历头部 -->     <view class="flex-around calendar-week">         <view class="view">一</view>         <view class="view">二</view>         <view class="view">三</view>         <view class="view">四</view>         <view class="view">五</view>         <view class="view">六</view>         <view class="view">日</view>     </view>     <!-- 日历主体 -->     <swiper class="swiper" style="height:{{swiperHeight}}rpx" bindchange="swiperChange" circular="{{true}}" current="{{swiperCurrent}}" duration="{{swiperDuration}}">         <swiper-item wx:for="{{[dateList0, dateList1, dateList2]}}" wx:for-index="listIndex" wx:for-item="listItem" wx:key="listIndex">             <view class="flex-start flex-wrap calendar-main" style="height:{{listItem.length/7*82}}rpx">                 <view wx:for="{{listItem}}" wx:key="dateList" class="day">                     <view class="bg {{item.month === selectDay.month?spotMap['y'+item.year+'m'+item.month+'d'+item.day]?spotMap['y'+item.year+'m'+item.month+'d'+item.day]:'':''}} {{(item.year === nowDay.year && item.month === nowDay.month && item.day === nowDay.day) ? 'now' : ''}} {{(item.year === selectDay.year && item.month === selectDay.month) ? (item.day === selectDay.day && oldCurrent === listIndex ?'select':''): 'other-month'}}" catchtap="selectChange" data-day="{{item.day}}" data-year="{{item.year}}" data-month="{{item.month}}">                         {{item.day}}                     </view>                 </view>             </view>         </swiper-item>     </swiper>     <view catchtap="openChange" class="flex list-open">         <view class="icon {{open?'fold':'unfold'}}"></view>     </view> </view>  

calendar.js

// component/calendar/calendar.js Component({     /**      * 组件的属性列表      */     properties: {         spotMap: { //标点的日期             type: Object,             value: {}         },         defaultTime: { //标记的日期,默认为今日             type: String,             value: ''         },         title: { //标题             type: String,             value: ''         },         goNow: { // 是否有快速回到今天的功能             type: Boolean,             value: true,         }     },      /**      * 组件的初始数据      */     data: {         selectDay: {}, //选中时间         nowDay: {}, //现在时间         open: false,         swiperCurrent: 1, //选中时间         oldCurrent: 1, //之前选中时间         dateList0: [], //0位置的日历数组         dateList1: [], //1位置的日历数组         dateList2: [], //2位置的日历数组         swiperDuration: 500,         swiperHeight: 0,         backChange: false, //跳过change切换     },      /**      * 组件的方法列表      */     methods: {         swiperChange(e) { // 日历滑动时触发的方法             if (this.data.backChange) {                 this.setData({                     backChange: false                 })                 return             }             //计算第三个索引             let rest = 3 - e.detail.current - this.data.oldCurrent             let dif = e.detail.current - this.data.oldCurrent             let date             if (dif === -2 || (dif > 0 && dif !== 2)) { //向右划的情况,日期增加                 if (this.data.open) {                     date = new Date(this.data.selectDay.year, this.data.selectDay.month)                     this.setMonth(date.getFullYear(), date.getMonth() + 1, undefined)                     this.getIndexList({                         setYear: this.data.selectDay.year,                         setMonth: this.data.selectDay.month,                         dateIndex: rest                     })                 } else {                     date = new Date(this.data.selectDay.year, this.data.selectDay.month - 1, this.data.selectDay.day + 7)                     this.setMonth(date.getFullYear(), date.getMonth() + 1, date.getDate())                     this.getIndexList({                         setYear: this.data.selectDay.year,                         setMonth: this.data.selectDay.month - 1,                         setDay: this.data.selectDay.day + 7,                         dateIndex: rest                     })                 }             } else { //向左划的情况,日期减少                 if (this.data.open) {                     date = new Date(this.data.selectDay.year, this.data.selectDay.month - 2)                     this.setMonth(date.getFullYear(), date.getMonth() + 1, undefined)                     this.getIndexList({                         setYear: this.data.selectDay.year,                         setMonth: this.data.selectDay.month - 2,                         dateIndex: rest                     })                 } else {                     date = new Date(this.data.selectDay.year, this.data.selectDay.month - 1, this.data.selectDay.day - 7)                     this.setMonth(date.getFullYear(), date.getMonth() + 1, date.getDate())                     this.getIndexList({                         setYear: this.data.selectDay.year,                         setMonth: this.data.selectDay.month - 1,                         setDay: this.data.selectDay.day - 7,                         dateIndex: rest                     })                 }             }             this.setData({                 oldCurrent: e.detail.current             })             this.setSwiperHeight(e.detail.current)         },         setSwiperHeight(index) { // 根据指定位置数组的大小计算长度             this.setData({                 swiperHeight: this.data[`dateList${index}`].length / 7 * 82 + 18             })         },         //更新指定的索引和月份的列表         getIndexList({             setYear,             setMonth,             setDay = void 0,             dateIndex         }) {             let appointMonth             if (setDay)                 appointMonth = new Date(setYear, setMonth, setDay)             else                 appointMonth = new Date(setYear, setMonth)             let listName = `dateList${dateIndex}`             this.setData({                 [listName]: this.dateInit({                     setYear: appointMonth.getFullYear(),                     setMonth: appointMonth.getMonth() + 1,                     setDay: appointMonth.getDate(),                     hasBack: true                 }),             })         },         //设置月份         setMonth(setYear, setMonth, setDay) {             const day = Math.min(new Date(setYear, setMonth, 0).getDate(), this.data.selectDay.day)             if (this.data.selectDay.year !== setYear || this.data.selectDay.month !== setMonth) {                 const data = {                     selectDay: {                         year: setYear,                         month: setMonth,                         day: setDay ? setDay : day                     },                 }                 if (!setDay) {                     data.open = true                 }                 this.setData(data, () => {                     this.triggerEvent("selectDay", this.data.selectDay)                 })             } else {                 const data = {                     selectDay: {                         year: setYear,                         month: setMonth,                         day: setDay ? setDay : day                     },                 }                 this.setData(data, () => {                     this.triggerEvent("selectDay", this.data.selectDay)                 })             }         },         //展开收起         openChange() {             this.setData({                 open: !this.data.open             })             this.triggerEvent("aaa", {                 a: 0             })             // 更新数据             const selectDate = new Date(this.data.selectDay.year, this.data.selectDay.month - 1, this.data.selectDay.day)             if (this.data.oldCurrent === 0) {                 this.updateList(selectDate, -1, 2)                 this.updateList(selectDate, 0, 0)                 this.updateList(selectDate, 1, 1)             } else if (this.data.oldCurrent === 1) {                 this.updateList(selectDate, -1, 0)                 this.updateList(selectDate, 0, 1)                 this.updateList(selectDate, 1, 2)             } else if (this.data.oldCurrent === 2) {                 this.updateList(selectDate, -1, 1)                 this.updateList(selectDate, 0, 2)                 this.updateList(selectDate, 1, 0)             }             this.setSwiperHeight(this.data.oldCurrent)         },         // 选中并切换今日日期         switchNowDate() {             const now = new Date()             const selectDate = new Date(this.data.selectDay.year, this.data.selectDay.month - 1, this.data.selectDay.day)             let dateDiff = (selectDate.getFullYear() - now.getFullYear()) * 12 + (selectDate.getMonth() - now.getMonth())             let diff = dateDiff === 0 ? 0 : dateDiff > 0 ? -1 : 1             const diffSum = (x) => (3 + (x % 3)) % 3             if (this.data.oldCurrent === 0) {                 this.updateList(now, -1, diffSum(2 + diff))                 this.updateList(now, 0, diffSum(0 + diff))                 this.updateList(now, 1, diffSum(1 + diff))             } else if (this.data.oldCurrent === 1) {                 this.updateList(now, -1, diffSum(0 + diff))                 this.updateList(now, 0, diffSum(1 + diff))                 this.updateList(now, 1, diffSum(2 + diff))             } else if (this.data.oldCurrent === 2) {                 this.updateList(now, -1, diffSum(1 + diff))                 this.updateList(now, 0, diffSum(2 + diff))                 this.updateList(now, 1, diffSum(0 + diff))             }             this.setData({                 swiperCurrent: diffSum(this.data.oldCurrent + diff),                 oldCurrent: diffSum(this.data.oldCurrent + diff),                 backChange: dateDiff !== 0,             })             this.setData({                 selectDay: {                     year: now.getFullYear(),                     month: now.getMonth() + 1,                     day: now.getDate()                 }             }, () => {                 this.triggerEvent("selectDay", this.data.selectDay)             })             this.setSwiperHeight(this.data.oldCurrent)         },         //日历主体的渲染方法         dateInit({             setYear,             setMonth,             setDay = this.data.selectDay.day,             hasBack = false         } = {             setYear: this.data.selectDay.year,             setMonth: this.data.selectDay.month,             setDay: this.data.selectDay.day,             hasBack: false         }) {             let dateList = []; //需要遍历的日历数组数据             let now = new Date(setYear, setMonth - 1) //当前月份的1号             let startWeek = now.getDay(); //目标月1号对应的星期             let resetStartWeek = startWeek == 0 ? 6 : startWeek - 1; //重新定义星期将星期天替换为6其余-1             let dayNum = new Date(setYear, setMonth, 0).getDate() //当前月有多少天             let forNum = Math.ceil((resetStartWeek + dayNum) / 7) * 7 //当前月跨越的周数             let selectDay = setDay ? setDay : this.data.selectDay.day             this.triggerEvent("getDateList", {                 setYear: now.getFullYear(),                 setMonth: now.getMonth() + 1             })             if (this.data.open) {                 //展开状态,需要渲染完整的月份                 for (let i = 0; i < forNum; i++) {                     const now2 = new Date(now)                     now2.setDate(i - resetStartWeek + 1)                     let obj = {};                     obj = {                         day: now2.getDate(),                         month: now2.getMonth() + 1,                         year: now2.getFullYear()                     };                     dateList[i] = obj;                 }             } else {                 //非展开状态,只需要渲染当前周                 for (let i = 0; i < 7; i++) {                     const now2 = new Date(now)                     //当前周的7天                     now2.setDate(Math.ceil((selectDay + (startWeek - 1)) / 7) * 7 - 6 - (startWeek - 1) + i)                     let obj = {};                     obj = {                         day: now2.getDate(),                         month: now2.getMonth() + 1,                         year: now2.getFullYear()                     };                     dateList[i] = obj;                 }             }             if (hasBack) {                 return dateList             }             this.setData({                 dateList1: dateList             })         },         //一天被点击时         selectChange(e) {             const year = e.currentTarget.dataset.year             const month = e.currentTarget.dataset.month             const day = e.currentTarget.dataset.day             const selectDay = {                 year: year,                 month: month,                 day: day,             }             if (this.data.open && (this.data.selectDay.year !== year || this.data.selectDay.month !== month)) {                 if ((year * 12 + month) > (this.data.selectDay.year * 12 + this.data.selectDay.month)) { // 下个月                     if (this.data.oldCurrent == 2)                         this.setData({                             swiperCurrent: 0                         })                     else                         this.setData({                             swiperCurrent: this.data.oldCurrent + 1                         })                 } else { // 点击上个月                     if (this.data.oldCurrent == 0)                         this.setData({                             swiperCurrent: 2                         })                     else                         this.setData({                             swiperCurrent: this.data.oldCurrent - 1                         })                 }                 this.setData({                     ['selectDay.day']: day                 }, () => {                     this.triggerEvent("selectDay", this.data.selectDay)                 })             } else if (this.data.selectDay.day !== day) {                 this.setData({                     selectDay: selectDay                 }, () => {                     this.triggerEvent("selectDay", this.data.selectDay)                 })             }         },         updateList(date, offset, index) {             if (this.data.open) { //打开状态                 const setDate = new Date(date.getFullYear(), date.getMonth() + offset * 1) //取得当前日期的上个月日期                 this.getIndexList({                     setYear: setDate.getFullYear(),                     setMonth: setDate.getMonth(),                     dateIndex: index                 })             } else {                 const setDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() + offset * 7) //取得当前日期的七天后的日期                 this.getIndexList({                     setYear: setDate.getFullYear(),                     setMonth: setDate.getMonth(),                     setDay: setDate.getDate(),                     dateIndex: index                 })             }         },     },     lifetimes: {         attached() {             let now = this.data.defaultTime ? new Date(this.data.defaultTime) : new Date()             let selectDay = {                 year: now.getFullYear(),                 month: now.getMonth() + 1,                 day: now.getDate()             }             this.setData({                 nowDay: {                     year: now.getFullYear(),                     month: now.getMonth() + 1,                     day: now.getDate()                 }             })             this.setMonth(selectDay.year, selectDay.month, selectDay.day)             this.updateList(now, -1, 0)             this.updateList(now, 0, 1)             this.updateList(now, 1, 2)             this.setSwiperHeight(1)         }     },     observers: {} }) 

calendar.json

{     "component": true,     "usingComponents": {} } 

calendar.wxss

/* component/calendar/calendar.wxss */  .icon {   background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACcUlEQVRYhe2WvWtUURDFf8dNVk1ETViMX4WNna22CopELBQUkYASgzFFUPBPsLGSgAqJGDRGBEUsRA0KIthaip2I/4CEoIR8JyP33lldl7fuR1AL9xSP3Xfvmzlz7pl5jyaa+O+hq0NDqDEV8sBGYA3wDZirP4TFhxvFApAD1gPz5TGqF2Xx2pK5puwA9uuPPUA30A48Bd43Ukg2gWpQTHwe2Iax5GRuA6//BoFuwQDQaUF6xaPYBFzCYryXf4yAoAc44We/INjgJvzqGwYwWg2e1Rqzogmt9MwTjgGngBXvgLB8Axh1HyiuiV7BwVoJ1KpAqPqMu70dtFbYNWDC7SqwfoMp0r9BLHbHi2qBa2nDk0A/aAmUF9oscR1pAikJIR4g3RXqUFIoxD0nOLQqAoLjwFlgOuyVKCDGve3KMY54BOqMrBTVDSQON0rgqLfajJCF5IJ7SmdeifBIICgISgQSbUCPYH+9BI4Ag8BidLzY4VXf+V01TmIM9BhU8Gc7gNOCfVn7s0y4N1SuNNuXhbYDDwU3qyX/QUIMm7Eo6HNj7gQueKe8KyfQ4guh2gPAZW+zWdAW4Al1JC+RYjTMBKA3xYpdcZE0O974rlxIXvDeDhv6gF1Kg6UrnrcYqTv5TwwLpi0VFRTd6oTmQB/AckUPrMS5LjpR9MU6n+2rSV7EfRQH1orSwOoC2w0WlQ+XZZ9qs/57CnQFLMnk47A4FdXYx8MYMJl8ECN9hPgSyxdNGM7qC3DLibyt9Ea3rHtmFddK8DzlURvYZ1c5GrA4ueZBr5S8EPp3JjNgyc061QgvsE9gk/4x0+qKN9FEE/8QwHd9qo6ectzgFAAAAABJRU5ErkJggg==");   background-size: 100% auto;   width: 32rpx;   height: 32rpx; }  .flex {   display: flex;   justify-content: space-between;   align-items: center; }  .swiper {   transition: height 0.3s; }  .header-wrap {   display: flex;   justify-content: space-between;   align-items: center; }  .today {   width: 88rpx;   height: 42rpx;   background: #F3F4F4;   border-radius: 22rpx;   font-size: 24rpx;   line-height: 42rpx;   color: #868D8D;   text-align: center;   margin-right: 6rpx; }  .today:active {   background: #dfdfdf;   color: #5f6464; }  .direction-column {   flex-direction: column; }  .flex1 {   flex: 1; }  .flex-center {   display: flex;   justify-content: center;   align-items: center; }  .flex-start {   display: flex;   justify-content: flex-start;   align-items: center; }  .flex-end {   display: flex;   justify-content: flex-end;   align-items: center; }  .flex-around {   display: flex;   justify-content: space-around;   align-items: center; }  .flex-wrap {   flex-wrap: wrap; }  .align-start {   align-items: flex-start; }  .align-end {   align-items: flex-end; }  .align-stretch {   align-items: stretch; }  .calendar {   font-family: "PingFang SC", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Helvetica, Arial, "Hiragino Sans GB", "Source Han Sans", "Noto Sans CJK Sc", "Microsoft YaHei", "Microsoft Jhenghei", sans-serif; }  .calendar .title {   padding: 10rpx 16rpx 10rpx 20rpx;   line-height: 60rpx;   font-size: 32rpx;   font-weight: 600;   color: #1C2525;   line-height: 44px;   letter-spacing:1px; }  .calendar .title .year-month {   margin-right: 20rpx; }  .calendar .title .icon {   padding: 0 16rpx;   font-size: 32rpx;   color: #999; }  .calendar .title .open {   background-color: #f6f6f6;   color: #999;   font-size: 22rpx;   line-height: 36rpx;   border-radius: 18rpx;   padding: 0 14rpx; }  .list-open {   position: relative;   justify-content: center; }  .list-open .icon::after {   content: '';   position: absolute;   top: 16rpx;   right: 60rpx;   display: block;   width: 278rpx;   height: 0rpx;   border-bottom: 2rpx solid rgba(214, 219, 219, 0.68); }  .list-open .icon::before {   content: '';   position: absolute;   top: 16rpx;   left: 60rpx;   display: block;   width: 278rpx;   height: 0rpx;   border-bottom: 2rpx solid rgba(214, 219, 219, 0.68); }  .fold {   transform: rotate(0deg); }  .unfold {   transform: rotate(180deg); }  .calendar .calendar-week {   line-height: 40rpx;   padding: 0 25rpx;   font-size: 28rpx;   color: #999; }  .calendar .calendar-week .view {   width: 100rpx;   text-align: center; }  .calendar .calendar-main {   padding: 18rpx 25rpx 0rpx;   transition: height 0.3s;   align-content: flex-start;   overflow: hidden; }  .calendar .calendar-main .day {   position: relative;   width: 100rpx;   color: #666;   text-align: center;   height: 82rpx; }  .calendar .calendar-main .day .bg {   height: 66rpx;   line-height: 66rpx;   font-size: 28rpx;   color: #333; }  .calendar .calendar-main .day .now {   width: 66rpx;   border-radius: 50%;   text-align: center;   color: #0EC0B8;   background: rgba(14, 192, 184, 0.2);   margin: 0 auto; }  .calendar .calendar-main .day .select {   width: 66rpx;   border-radius: 50%;   text-align: center;   color: #fff;   background: #0EC0B8;   margin: 0 auto; }  .calendar .calendar-main .day .spot::after {   position: absolute;   content: "";   display: block;   width: 8rpx;   height: 8rpx;   bottom: 22rpx;   background: #0EC0B8;   border-radius: 50%;   left: 0;   right: 0;   margin: auto; }  .calendar .calendar-main .day .deep-spot::after {   position: absolute;   content: "";   display: block;   width: 8rpx;   height: 8rpx;   bottom: 22rpx;   background: #FF7416;   border-radius: 50%;   left: 0;   right: 0;   margin: auto; }  .calendar .calendar-main .day .other-month {   color: #ccc; }  .header-wrap .month {   font-size: 28rpx;   color: #929797;   line-height: 40rpx; }