微信小程序–创建一个日历组件
- 可以创建一个日历组件,来展示当前月份的日期,并支持切换月份的功能。
一、目录结构
/pages
/calendar
calendar.wxml
calendar.scss
calendar.js
calendar.json
二、calendar.wxml
<view class="calendar">
<view class="header">
<view bindtap="changeMonth" data-direction="prev">
<van-icon name="arrow-left" />
</view>
<text>{{year}}年{{month}}月</text>
<van-icon name="arrow" bindtap="changeMonth" data-direction="next" />
</view>
<view class="days">
<view class="week">
<text>日</text>
<text>一</text>
<text>二</text>
<text>三</text>
<text>四</text>
<text>五</text>
<text>六</text>
</view>
<view class="dates">
<block wx:for="{{days}}" wx:key="index">
<view class="date">{{item}}</view>
</block>
</view>
</view>
</view>
三、calendar.scss
.calendar {
width: 100%;
border-radius: 15rpx;
background-color: #fff;
padding: 20rpx;
}
.header {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size:32rpx;
}
.days {
margin-top: 20px;
}
.week {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
text-align: center;
margin-bottom: 20px;
}
.dates {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 10px 5px;
}
.date {
width: 100%;
height: 60px;
text-align: center;
padding: 10px;
background-color: #f0f0f0;
color: #000;
}
四、calendar.js
Page({
data: {
year: new Date().getFullYear(),
month: new Date().getMonth() + 1,
days: [],
},
onLoad() {
this.loadCalendar();
},
loadCalendar() {
const { year, month } = this.data;
// 获取当月的第一天是星期几
const firstDay = new Date(year, month - 1, 1).getDay();
// 获取当月的天数
const totalDays = new Date(year, month, 0).getDate();
// 创建日期数组
const days = [];
// 填充空白日期
for (let i = 0; i < firstDay; i++) {
days.push('');
}
// 填充实际日期
for (let i = 1; i <= totalDays; i++) {
days.push(i);
}
this.setData({ days });
},
changeMonth(event) {
const direction = event.currentTarget.dataset.direction;
let { year, month } = this.data;
if (direction === 'prev') {
month--;
if (month < 1) {
month = 12;
year--;
}
} else if (direction === 'next') {
month++;
if (month > 12) {
month = 1;
year++;
}
}
this.setData({ year, month }, () => {
this.loadCalendar();
});
}
});
五、效果图(样式可以按需更改)
六、padStart
padStart(2, '0')
是 JavaScript 字符串的方法,用于填充字符串的开头直到指定的长度。
使用了 padStart(2, '0')
来确保日期和月份都是两位数格式。
str.padStart(targetLength, padString);
-
targetLength
是目标字符串的最终长度。 -
padString
是用于填充的字符串(如果字符串长度不够,使用这个字符串填充,直到目标长度为止)。
在 padStart(2, '0')
中,意思是如果原字符串的长度小于 2,则用 '0'
在字符串的开头进行填充,直到字符串的长度为 2。
- 案列:
'5'.padStart(2, '0'); // '05'
'12'.padStart(2, '0'); // '12'
'123'.padStart(5, '0'); // '00123'
七、实现高亮当前日期,给日期添加点击事件,并高亮显示
calendar.wxml
<view class="dates">
<block wx:for="{{days}}" wx:key="index">
<view class="date {{item.isToday ? 'highlight-today' : ''}} {{isChooseDate==item.day ? 'choose-day' : ''}}" bindtap="showEventDetail" data-day="{{item}}">{{item.day}}</view>
</block>
</view>
calendar.js
loadCalendar() {
const {
year,
month
} = this.data;
// 获取当月的第一天是星期几
const firstDay = new Date(year, month - 1, 1).getDay();
// 获取当月的天数
const totalDays = new Date(year, month, 0).getDate();
// 获取今天的日期(用于高亮显示)
const today = new Date();
const todayDate = `${today.getFullYear()}-${(today.getMonth() + 1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`;
// 创建日期数组
const days = [];
// 填充空白日期
for (let i = 0; i < firstDay; i++) {
days.push('');
}
// 填充实际日期
for (let i = 1; i <= totalDays; i++) {
const day = `${year}-${month.toString().padStart(2, '0')}-${i.toString().padStart(2, '0')}`;
const isToday = day === todayDate; // 如果是今天的日期,则标记为今天
days.push({ day: i,isToday });
}
this.setData({
days,
selectedDate:this.data.selectedDate?this.data.selectedDate:todayDate
});
},
changeMonth(event) {
const direction = event.currentTarget.dataset.direction;
let {
year,
month
} = this.data;
if (direction === 'prev') {
month--;
if (month < 1) {
month = 12;
year--;
}
} else if (direction === 'next') {
month++;
if (month > 12) {
month = 1;
year++;
}
}
this.setData({
year,
month,
isChooseDate:''
}, () => {
this.loadCalendar();
});
},
// 显示事件详情
showEventDetail(event) {
const day = event.currentTarget.dataset.day.day;
const selectedDate = `${this.data.year}-${this.data.month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
this.setData({
isChooseDate:day,
selectedDate:selectedDate
})
},
calendar.scss
.choose-day{
border:1px solid #65b778;
color: #65b778;
font-weight: bold;
background-color: #fff;
}
.highlight-today{
background-color: #65b778;
color: #fff;
font-weight: bold;
}
- 效果图
八、滑动切换日历月份
calendar.html
<view class="calendar" bindtouchstart="touchStart" bindtouchend="touchEnd"></view>
calendar.js
data: {
startX: 0, // 触摸起始位置
startY: 0, // 触摸起始位置
minSwipeDistance: 50 // 设置最小滑动距离,单位:px
},
// 触摸开始事件
touchStart(e) {
this.setData({
startX: e.touches[0].clientX,
startY: e.touches[0].clientY
});
},
// 触摸结束事件
touchEnd(e) {
const endX = e.changedTouches[0].clientX;
const endY = e.changedTouches[0].clientY;
const dx = endX - this.data.startX; // 水平滑动距离
const dy = endY - this.data.startY; // 垂直滑动距离
// 判断是否为左右滑动(忽略上下滑动)
if (Math.abs(dx) > Math.abs(dy)) {
if (Math.abs(dx) >= this.data.minSwipeDistance) { // 只有当滑动距离超过阈值时才切换,防止误触
if (dx > 0) {
// 向右滑动,切换到上个月
this.changeMonthBySwipe('prev');
} else if (dx < 0) {
// 向左滑动,切换到下个月
this.changeMonthBySwipe('next');
}
}
}
},
// 根据滑动方向切换月份
changeMonthBySwipe(direction) {
let {
year,
month
} = this.data;
if (direction === 'prev') {
month--;
if (month < 1) {
month = 12;
year--;
}
} else if (direction === 'next') {
month++;
if (month > 12) {
month = 1;
year++;
}
}
this.setData({
year,
month,
isChooseDate: ''
}, () => {
this.loadCalendar();
});
},