先看一下效果图
本篇文章只是在原文的基础上进行小修改和代码的部分优化,里面注释我已经写的很清楚了,这个组件可以用来做签到,买火车票那种的组件等等;屁话不多说,直接上代码
**
子组件代码
**
组件wxml代码
<view class="calendar-main-container {{isBtnShowModal===0?'calendar-transit':''}} {{isShowModal?'':'calendar-unactive'}}">
<!-- 年月份、左右箭头 -->
<view class="year-month-container">
<view bindtap="preMonth">
<i class="iconfont icon-fanhui-copy"></i>
</view>
<view class="text_center" style="text-align:center;">{{curYear+'-'+curMonth}}</view>
<view style="text-align:right;" bindtap="nextMonth">
<i class="iconfont icon-fanhui-copy1"></i>
</view>
</view>
<!-- 日历主体部分 -->
<view class="calendar-panel calendar-box-container-two">
<view class="calendar-box">
<view class="weekday-label">日</view>
<view class="weekday-label">一</view>
<view class="weekday-label">二</view>
<view class="weekday-label">三</view>
<view class="weekday-label">四</view>
<view class="weekday-label">五</view>
<view class="weekday-label">六</view>
</view>
<!-- 渲染每月多少天 -->
<view class="calendar-box" wx:for="{{dateList}}" wx:for-item="week"
style="{{index==0?'justify-content:flex-end':''}}">
<!-- 此处view的data-不是为了向js传值,而只是自定义属性向css伪元素传attr() -->
<view class="weekday-label {{item.value===selectedDate?'current-date':''}} {{item.value===curSelectedDate?'current-dates':''}} {{item.event?'actived_date':''}}" wx:for="{{week}}" data-event="{{item.event}}">
<view class="" bindtap="handleSelectDate" data-date="{{item}}">
{{item.date}}</view>
</view>
</view>
</view>
</view>
<view class="calendar_task" wx:if="{{respondShowModal && isShowModal}}" bindtap="closeModal"></view>
组件wxss代码
@import "./icon/icon.wxss";
/* calendar-main-container是整体的大容器 */
.calendar-main-container{
width: 100%;
padding-bottom: 3rpx;
background-color: white;
}
/* 弹出隐藏过渡动画 */
.calendar-transit{
position: fixed;
bottom: 0;
left: 0;
animation-delay: -.4s;
z-index: 100000 !important;
animation: transfer .6s linear;
}
@keyframes transfer{
0%{
transform: translateY(100%);
}
100%{
transform: translateY(0);
}
}
.calendar-unactive{
transition: all .3s ease;
transform: translateY(100%);
}
/* 年月份、左右箭头 */
.year-month-container{
display: flex;
align-items: center;
justify-content: space-around;
width: 100%;
height: 56rpx;
overflow: hidden;
padding-bottom: 16rpx;
}
/* .year-month-content>view{
width: 29.5%;
} */
/* 日历主体部分 */
.calendar-box-container{
width: 100%;
height: calc(100% - 56rpx);
}
.calendar-box-container-two{
display: flex;
flex-direction: column;
justify-content: space-around;
}
.calendar-box{
display: flex;
align-items: center;
width: 100%;
height: calc(100% / 6);
background: #fff;
overflow: hidden;
}
/* 周 容器 */
.weekday-label{
display: flex;
align-items: center;
justify-content: center;
width: calc(100% / 7);
font-size: 27rpx;
padding: 12rpx 0;
overflow: hidden;
border-radius: 50%;
white-space: nowrap;
text-overflow: ellipsis;
}
.weekday-label>view{
padding: 20%;
box-sizing: border-box;
}
.select_icon{
width: 30rpx;
height: 30rpx;
}
/* 当前日期样式 */
.current-date{
position: relative;
color: white;
overflow: hidden;
border-radius: 50%;
background-color: #07c160;
}
.current-dates{
position: relative;
color: rgba(0,0,0,.5);
background: rgba(0,0,0,.1);
}
.current-dates::before{
position: absolute;
top: 3rpx;
left: 50%;
content: "今天";
color: blue;
font-size: 18rpx;
transform: translateX(-50%);
}
.actived_date{
overflow: hidden;
position: relative;
}
.actived_date::after{
position: absolute;
bottom: 7%;
left: 50%;
color: blue;
font-size: 16rpx;
content: attr(data-event);
transform: translateX(-50%);
}
/* .show_box{
padding: 20rpx;
font-size: 26rpx;
} */
/* 灰色蒙层 */
.calendar_task{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99999 !important;
background-color: rgba(0,0,0,.5);
}
组件js代码
// components/calendar/calendar.js
Component({
/**
* 组件的属性列表
*/
properties: {
dateTimes:{
type:Array,
value:[]
},
isBtnShowModal:{ //是否作为日期组件由按钮触发弹出(为0时是)
type:Number,
value:1
},
respondShowModal:{ //只有这个为1时,“和遮罩层有关的事件才会响应”
type:Number,
value:1
}
},
/**
* 组件的初始数据
*/
data: {
curSelectedDate: '', //当前是几月几号
selectedDate: '', //选中的几月几号
selectedWeek: '', //选中的是星期几
curYear: 2017, //当前年份
curMonth: 0, //当前月份
daysCountArr: [31,28,31,30,31,30,31,31,30,31,30,31],
weekArr: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
dateList: [],
nowEvent: ''
},
lifetimes:{
attached(){
//初始化年月日
const { weekArr, nowEvent } = this.data
var today = new Date()
var curYear = today.getFullYear()
var curMonth = today.getMonth() + 1
var date = today.getDate()
var i = today.getDay()
var selectedDate = `${curYear}-${curMonth}-${date}`
var nowDate = `${curMonth}-${date}`
var selectedWeek = weekArr[i]
this.setData({
curYear,
curMonth,
selectedDate,
curSelectedDate: selectedDate,
selectedWeek,
nowDate,
isShowModal: true
})
this.getDateList(curYear,curMonth-1,nowDate)
this.triggerEvent('timeload',{selectedDate,selectedWeek,event:nowEvent})
}
},
/**
* 组件的方法列表
*/
methods: {
// 获取当前年月日
getDateList(year,month,nowDate){
const that = this
const { daysCountArr, dateTimes } = that.data
const tDateTime = that.properties.dateTimes
//对2月份天数进行处理
if(year % 4 === 0 && year % 100 !== 0){
daysCountArr[1] = 29
this.setData({ daysCountArr })
}
var dateList = []
dateList[0] = []
var weekIndex = 0
//循环遍历月份天数
for(var i= 0; i < daysCountArr[month]; i++){
var week = new Date(Date.UTC(year,month,i+1)).getDay()
// console.log(week)
//将处理后的天数push到dateList
//在这里可以做签到的功能,我们当月签到天数都是从后台获取的,假设这月30天,我们一共签到了10天,后台就会在一个数组里面返回 //10个isSign:true,代表签到了十天,我们就可以push到dateList中,根据这个isSign用wx:if来进行判断,布局只需要小修改即可
dateList[weekIndex].push({
value: `${year}-${month+1}-${i+1}`,
dateTime: `${month+1}-${i+1}`,
date: i + 1,
week,
//仅为展示测试
//isSign: item.isSign
})
// console.log(tDateTime)
//处理每个月中的节日
for(let k in dateTimes){
// console.log(dateList[weekIndex])
for(let j in dateList[weekIndex]){
// 判断当前月份日期是否有和节日列表中的日期相等
if(dateList[weekIndex][j].dateTime === tDateTime[k].day){
dateList[weekIndex][j].event = tDateTime[k].target
}
// 判断月份
if(dateList[weekIndex][j].value === tDateTime[k].day){
dateList[weekIndex][j].event = tDateTime[k].target
}
if(nowDate === tDateTime[k].day){
that.setData({
nowEvent: tDateTime[k].target
})
}
}
}
if(week === 6){
weekIndex++
dateList[weekIndex] = []
}
}
that.setData({ dateList })
},
//选择日期
handleSelectDate(e){
const that = this
let { value, week, event } = e.currentTarget.dataset.date
let { weekArr } = that.data
// console.log(that.data.dateList)
that.setData({
selectedDate: value,
selectedWeek: weekArr[week]
})
//向父组件传递数据
this.triggerEvent('timechanged',{
selectedDate: value,
selectedWeek: weekArr[week],
event: event || ''
})
},
//上个月
preMonth(){
var that = this
let { curYear, curMonth } = that.data
curYear = curMonth - 1 ? curYear : curYear-1
curMonth = curMonth - 1 ? curMonth - 1 : 12
that.setData({
curYear,
curMonth
})
that.getDateList(curYear,curMonth-1,this.data.nowDate)
},
//下个月
nextMonth(){
var that = this
let { curYear, curMonth } = that.data
curYear = curMonth + 1 === 13 ? curYear + 1 : curYear
curMonth = curMonth + 1 === 13 ? 1 : curMonth + 1
console.log(curYear,curMonth)
that.setData({
curYear,
curMonth
})
that.getDateList(curYear,curMonth-1,this.data.nowDate)
},
//关闭弹层
closeModal(){
if(this.properties.respondShowModal === 1){
this.setData({
isShowModal:false
})
}
}
}
})
**
在父组件中使用
**
json中引入
"usingComponents": {
"calendar":"../../components/calendar/calendar"
}
wxml代码
<view>第一种方式</view>
<view>
<calendar isBtnShowModal="1" respondShowModal="0" dateTimes="{{dateTimes}}" bind:timeload="timeload"
bind:timechanged="timechanged"></calendar>
</view>
<view style="margin-top:30rpx;margin-bottom:20rpx;border-top:1rpx solid rgba(0,0,0,.15)">第二种使用方式:弹出式(请点击下面那个按钮)</view>
<view class="basic_box">
<view class="departments location" bindtap="openCalendarModal">
<view class="depart_title">选择日期</view>
<view wx:if="{{nowDate&&nowWeek}}" class="placeholder depart_content">{{nowDate}} {{nowWeek}}
</view>
<view class="placeholder depart_content befselect" wx:else>请选择日期</view>
</view>
</view>
<!-- 引用自定义组件calendar -->
<calendar wx:if="{{selected}}" isBtnShowModal="0" respondShowModal="1" dateTimes="{{dateTimes}}" bind:timeload="timeload"
bind:timechanged="timechanged"></calendar>
js代码
Page({
/**
* 页面的初始数据
*/
data: {
dateTimes:[
{day:'4-5',target:'清明节'},
{day:'5-1',target:'劳动节'},
{day:'10-1',target:'国庆节'},
{day:'10-2',target:'中秋节'},
{day:'2020-10-24',target:'程序员节'}
],
selected:false,
nowDate:'',
nowWeek:''
},
//打开弹出层
openCalendarModal(){
this.setData({
selected: !this.data.selected,
nowDate: this.selectedDate,
nowWeek: this.selectedWeek
})
},
timeload(e){
console.log(e.detail)
const { selectedDate, selectedWeek } = e.detail
// 保存到变量中,在刚打开组件时显示到页面上初始值
this.selectedDate = selectedDate
this.selectedWeek = selectedWeek
},
//日期改变时触发
timechanged(e){
console.log(e.detail)
const { selectedDate, selectedWeek } = e.detail
this.setData({
nowDate: selectedDate,
nowWeek: selectedWeek
})
},
})
wxss代码
.select{
display: inline-block;
margin: 20rpx;
border: 1rpx solid rgba(0,0,0,.2);
padding: 6rpx 10rpx;
}
.basic_box{
width: 100%;
border-top: 1rpx solid rgba(0,0,0,.08);
border-bottom: 1rpx solid rgba(0,0,0,.08);
box-sizing: border-box;
padding: 0 0 0 26rpx;
}
.basic_box .departments{
width: 100%;
height: 96rpx;
display: flex;
align-items: center;
font-size: 36rpx;
font-weight: 347;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.basic_box .departments:nth-child(2){
border-top: 1rpx solid rgba(0,0,0,.08);
border-bottom: 1rpx solid rgba(0,0,0,.08);
}
.basic_box .location{
position: relative;
border-bottom: 1rpx solid rgba(0,0,0,.009);
display: flex;
align-items: flex-start;
padding-top: 20rpx;
}
.basic_box .desc{
position: absolute;
right: 19rpx;
bottom: 4rpx;
color: rgb(63,142,255);
font-size: 23rpx;
}
.departments .depart_title{
width: 20%;
}
.departments .depart_content{
margin-left: 10%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.departments .placeholder{
width: 69%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.departments .befselect{
color: rgba(0,0,0,.6);
}
本文转载自:https://yunxiaomeng.blog.youkuaiyun.com/article/details/108821829
github地址:https://github.com/1314mxc/yunUI