微信小程序--创建一个日历组件

时间:2024-12-13 21:26:37

微信小程序–创建一个日历组件

  • 可以创建一个日历组件,来展示当前月份的日期,并支持切换月份的功能。
一、目录结构
/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();
    });
  },