[组件封装]微信小程序-日历

描述

切换月份, 当天文案为今天, 日期背景变色, 日期红点标识, 点击选中日期.

效果

源码

calendar.wxml

<view class="component">
  <view class="header">
    <view bindtap="handlePrevMonthClick">{{'<'}}</view>
    <view>{{year}}年{{month}}月</view>
    <view bindtap="handleNextMonthClick">></view>
  </view>
  <view>
    <view class="week">周一</view>
    <view class="week">周二</view>
    <view class="week">周三</view>
    <view class="week">周四</view>
    <view class="week">周五</view>
    <view class="week">周六</view>
    <view class="week">周日</view>
  </view>
  <view class="daybox">
    <block wx:for="{{dayList}}" wx:key="{{index}}">
      <view wx:if="{{item.day}}" class="day {{item.day === day ? 'day-checked': ''}} {{item.bg ? 'day-bg' : ''}}" data-day="{{item.day}}" bindtap="handleDayClick">
        <view>{{item.isToday ? '今天' : item.day}}</view>
        <view class="point" wx:if="{{item.point}}"></view>
      </view>
      <view wx:else class="day"></view>
    </block>
  </view>
</view>

calendar.js

const weekNameMap = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];

Component({
  properties: {
    mydate: String,  // 选中的天  Date String 格式
    mylist: Array,
  },

  data: {
    year: null,
    month: null,
    day: null,
    list: [],
  },

  lifetimes: {
    attached: function () {
      const now = new Date();
      this.setData({
        year: now.getFullYear(),
        month: now.getMonth() + 1,
        day: now.getDate(),
      }, this.calcDayList)
    },
  },

  observers: {
    'mydate': function (mydate) {
      let date = new Date(mydate);
      this.setData({
        year: date.getFullYear(),
        month: date.getMonth() + 1,
        day: date.getDate(),
      }, this.calcDayList);
    },

    'mylist': function (mylist) {
      this.setData({ list: mylist }, this.calcDayList);
    },
  },

  methods: {

    // 获取当月共多少天
    getThisMonthDays: function (year, month) {
      return new Date(year, month, 0).getDate()
    },

    // 获取当月第一天星期几   0 星期日
    getFirstDayOfWeek: function (year, month) {
      return new Date(Date.UTC(year, month - 1, 1)).getDay();
    },


    calcDayList: function () {
      const { year, month, list, } = this.data;

      let totalDay = this.getThisMonthDays(year, month);
      let firstDay = this.getFirstDayOfWeek(year, month);

      let dayList = [];
      for (let i = 0; i < (totalDay); i++) {
        dayList.push({
          day: i + 1,
          weekName: weekNameMap[(firstDay + i) % 7],
        })
      }

      // 向前添加
      for (let i = 0; i < (firstDay || 7) - 1; i++) {
        dayList.unshift({ day: 0, });
      }

      // 向后添加
      for (let i = 0; i < 42 - totalDay - ((firstDay || 7) - 1); i++) {
        dayList.push({ day: 0, });
      }

      // 当天
      let now = new Date();
      if (now.getFullYear() === year && now.getMonth() + 1 === month) {
        (dayList.find(d => d.day === now.getDate()) || {}).isToday = true;
      }

      // 业务数据处理
      list.forEach(item => {
        let find = dayList.find(d => d.day === item.day);
        if (find) {
          Object.assign(find, item);
        }
      })

      this.setData({ dayList, });
    },

    // 点击上个月
    handlePrevMonthClick: function () {
      let year = this.data.year;
      let month = this.data.month;
      if (this.data.month === 1) {
        year = this.data.year - 1;
        month = 12;
      } else {
        month = this.data.month - 1;
      }
      this.handleDateChange({ year, month });
    },

    // 点击下个月
    handleNextMonthClick: function () {
      let year = this.data.year;
      let month = this.data.month;
      if (this.data.month === 12) {
        year = this.data.year + 1;
        month = 1;
      } else {
        month = this.data.month + 1;
      }
      this.handleDateChange({ year, month });
    },

    // 点击 天
    handleDayClick: function (e) {
      const { day } = e.currentTarget.dataset;
      this.handleDateChange({ day })
    },

    // 处理日期变化
    handleDateChange: function (time) {
      const { year, month, day } = this.data;
      let date = { year, month, day, ...time };
      if (!this.data.mydate) {
        this.setData({ ...date });
        if (time.year || time.month) this.calcDayList();
      }
      this.triggerEvent('mydatechange', { date: new Date(`${date.year}/${date.month}/${date.day}`).toString() })
    }



  }
})

calendar.wxss

.component {
  background: #fff;
}
.header {
  display: flex;
  justify-content: space-around;
  padding: 20rpx;
  border-top: 1px solid #eee;
}
.header view {
  height: 80rpx;
  line-height: 80rpx;
  font-size: 40rpx;
  color: rgba(0, 0, 0, 0.85);
  min-width: 100rpx;
}
.header view:nth-child(2n-1) {
  font-size: 50rpx;
}

.week {
  display: inline-block;
  width: 107rpx;
  line-height: 2;
  color: rgba(0, 0, 0, 0.45);
  font-size: 28rpx;
  text-align: center;
}

.daybox {
  display: flex;
  flex-wrap: wrap;
  border-bottom: 1px solid #eee;
}

.day {
  width: 107rpx;
  height: 107rpx;
  box-sizing: border-box;
  text-align: center;
  line-height: 2;
  color: rgba(0, 0, 0, 0.85);
  border: 4rpx solid #fff;
}

.day:nth-child(7n), .day:nth-child(7n-1) {
  color: #ff9b80;
}

.day-checked {
  border: 4rpx solid #ffa78f!important;
  border-radius: 10rpx;
}
.day-bg {
  background: #ffe9e4!important;
}

.point {
  width: 10rpx;
  height: 10rpx;
  border-radius: 50%;
  background: #ff876d;
  margin: 0 auto;
  margin-top: 5rpx;
}

calendar.json

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

使用例子

参数 类型 默认值 说明
mydate? String 当天时间字符串 选中的日期
mylist? Array [] 当月数据
handleDateClick? ({ detail: { date } }) => void 点击某天的的回调

test.wxml

<calendar mydate="{{mydate}}" mylist="{{list}}" bindmydatechange="handleDateClick" />

test.js

Page({  
  data: {
    mydate: new Date().toString(),
    mylist: [
      { day: 1,       // 当月天
        bg: true,     // 是否显示背景
        point: true,  // 是否显示圆点
      },
      { day: 3, bg: true },
      { day: 4, bg: true },
      { day: 5, bg: true, point: true },
      { day: 6, bg: true, point: true },
      { day: 7, point: true },
      { day: 8, point: true },
      { day: 9, point: true },
    ]
  },

  handleDateClick: function ({ detail: { date } }) {
    this.setData({ mydate: date });
  },

})

test.json

{
  "navigationBarTitleText": "demo",
  "usingComponents": {
    "calendar": "/components/calendar/calendar"
  }
}

注意

组件properties的数据类型不支持Date, 所以日期使用字符串格式传递。


猜你喜欢

转载自www.cnblogs.com/whosMeya/p/12557443.html