小程序-日历

日历.png

日历-修改年月.png

日历组件.png

-- 日历组件
calendar.wxml:

<view class="calendar">
    <view class="title">
        <!-- 上月 -->
        <view class="modify_btn" bindtap="lastMonth">
            <image class="modify_icon" src="/img/icon_return.png"></image>
        </view>
        <!-- 选择修改-年/月 -->
        <picker class="year-month" mode="date" fields="month" value="{{selectDay.year+'-'+selectDay.month}}" bindchange="editMonth">
            {{selectDay.year}}年{{selectDay.month>9?selectDay.month:"0"+selectDay.month}}月
        </picker>
        <!-- 下月 -->
        <view class="modify_btn" bindtap="nextMonth">
            <image class="modify_icon" src="/img/icon_enter.png"></image>
        </view>
    </view>

    <!-- 日历头部 -->
    <view class="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>

    <!-- 日历主体 -->
    <view class="calendar-main">
        <view class="day" wx:for="{{dateList}}" wx:key="index">
            <view class="bg {{(item.year === selectDay.year && item.month === selectDay.month) ? (item.day === selectDay.day?'select':''): 'other-month'}}" catchtap="selectChange" data-day="{{item.day}}" data-year="{{item.year}}" data-month="{{item.month}}" data-date-string="{{item.dateString}}">
                {{item.day}}
            </view>
            <view class="spot" wx:if="{{item.spot}}"></view>
        </view>
    </view>
</view>

calendar.wxss:

/* 日历 */
.calendar {
  width: 100%;
  background: #FCFDFE;
  border: 1rpx solid #E6EBF8;
  border-radius: 20rpx;
}
/* 日历-标题显示日期 */
.calendar .title {
  width: 100%;
  box-sizing: border-box;
  padding: 41rpx 0;
  border-bottom: 1rpx solid rgba(153, 153, 153, 0.2);
  font-size: 32rpx;
  color: #333333;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
/* 日历-日期修改月按钮 */
.calendar .title .modify_btn {
  flex: 1;
  text-align: center;
  padding: 0 16rpx;
}
/* 日历-日期修改月按钮图标 */
.calendar .title .modify_icon {
  width: 12rpx;
  height: 20rpx;
}

/* 日历头部 */
.calendar .calendar-week {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-sizing: border-box;
  padding: 30rpx;
}
/* 日历头部-每项 */
.calendar .calendar-week .view {
  width: 14.2%;
  text-align: center;
  font-size: 28rpx;
  color: #666;
}


/* 日历主体 */
.calendar .calendar-main {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: center;
  
  box-sizing: border-box;
  padding: 30rpx;
  transition: height 0.3s;
  align-content: flex-start;
  overflow: hidden;

  font-size: 28rpx;
}
/* 日历主体-每项 */
.calendar .calendar-main .day {
  position: relative;
  width: 14.2%;
  text-align: center;
  box-sizing: border-box;
  padding-bottom: 30rpx;
}
/* 日历主体-日-数据 */
.calendar .calendar-main .day .bg {
  height: 60rpx;
  line-height: 60rpx;
  font-size: 28rpx;
  color: #666;
}
/* 日历主体-日-选中数据 */
.calendar .calendar-main .day .select {
  width: 60rpx;
  border-radius: 50%;
  text-align: center;
  color: #fff;
  background: #1E44B2;
  margin: 0 auto;
}
/* 日历主体-日-不是当月的日期*/
.calendar .calendar-main .day .other-month {
  color: rgba(153, 153, 153, 0.8);
}
/* 日历主体-日-标点 */
.calendar .calendar-main .day .spot {
  width: 8rpx;
  height: 8rpx;
  background-color: #1E44B2;
  border-radius: 50%;
  margin: 6rpx auto 0;
}

calendar.json:

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

calendar.js:

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    spot: {
      type: Array,
      value: []
    },
    defaultTime: {
      type: String,
      value: ''
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    dateList: [], //日历主体渲染数组
    selectDay: {}, //选中时间
  },

  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 时间戳转化为年 月 日 时 分 秒
     * time: 需要被格式化的时间,可以被new Date()解析即可
     * format:格式化之后返回的格式,年月日时分秒分别为Y, M, D, h, m, s,这个参数不填的话则显示多久前
     */
    formatTime(time, format) {
      function formatNumber(n) {
        n = n.toString()
        return n[1] ? n : '0' + n
      }

      function getDate(time, format) {
        const formateArr = ['Y', 'M', 'D', 'h', 'm', 's']
        const returnArr = []
        const date = new Date(time)
        returnArr.push(date.getFullYear())
        returnArr.push(formatNumber(date.getMonth() + 1))
        returnArr.push(formatNumber(date.getDate()))
        returnArr.push(formatNumber(date.getHours()))
        returnArr.push(formatNumber(date.getMinutes()))
        returnArr.push(formatNumber(date.getSeconds()))
        for (const i in returnArr) {
          format = format.replace(formateArr[i], returnArr[i])
        }
        return format
      }

      function getDateDiff(time) {
        let r = ''
        const ft = new Date(time)
        const nt = new Date()
        const nd = new Date(nt)
        nd.setHours(23)
        nd.setMinutes(59)
        nd.setSeconds(59)
        nd.setMilliseconds(999)
        const d = parseInt((nd - ft) / 86400000)
        switch (true) {
          case d === 0:
            const t = parseInt(nt / 1000) - parseInt(ft / 1000)
            switch (true) {
              case t < 60:
                r = '刚刚'
                break
              case t < 3600:
                r = parseInt(t / 60) + '分钟前'
                break
              default:
                r = parseInt(t / 3600) + '小时前'
            }
            break
          case d === 1:
            r = '昨天'
            break
          case d === 2:
            r = '前天'
            break
          case d > 2 && d < 30:
            r = d + '天前'
            break
          default:
            r = getDate(time, 'Y-M-D')
        }
        return r
      }
      if (!format) {
        return getDateDiff(time)
      } else {
        return getDate(time, format)
      }
    },
    //picker设置月份
    editMonth(e) {
      const arr = e.detail.value.split("-")
      const year = parseInt(arr[0])
      const month = parseInt(arr[1])
      this.setMonth(year, month)
    },
    //上月切换按钮点击
    lastMonth() {
      const lastMonth = new Date(this.data.selectDay.year, this.data.selectDay.month - 2)
      const year = lastMonth.getFullYear()
      const month = lastMonth.getMonth() + 1
      this.setMonth(year, month)
    },
    //下月切换按钮点击
    nextMonth() {
      const nextMonth = new Date(this.data.selectDay.year, this.data.selectDay.month)
      const year = nextMonth.getFullYear()
      const month = nextMonth.getMonth() + 1
      this.setMonth(year, month)
    },
    //设置月份
    setMonth(setYear, setMonth, setDay) {
      if (this.data.selectDay.year !== setYear || this.data.selectDay.month !== setMonth) {
        const day = Math.min(new Date(setYear, setMonth, 0).getDate(), this.data.selectDay.day)
        const time = new Date(setYear, setMonth - 1, setDay ? setDay : day)
        const data = {
          selectDay: {
            year: setYear,
            month: setMonth,
            day: setDay ? setDay : day,
            dateString: this.formatTime(time, "Y-M-D")
          }
        }
        data.open = true;
        this.setData(data)
        this.dateInit(setYear, setMonth)
        this.setSpot();
        // 将修改后的日期-传到父组件
        this.triggerEvent("calendarChange", this.data.selectDay)
      }
    },
    //设置日历底下是否展示小圆点
    setSpot() {
      const timeArr = this.data.spot.map(item => {
        return this.formatTime(item, "Y-M-D")
      })
      this.data.dateList.forEach(item => {
        if (timeArr.indexOf(item.dateString) !== -1) {
          item.spot = true
        } else {
          item.spot = false
        }
      })
      this.setData({
        dateList: this.data.dateList
      })
    },
    //日历主体的渲染方法
    dateInit(setYear = this.data.selectDay.year, setMonth = this.data.selectDay.month) {
      let dateList = []; //需要遍历的日历数组数据
      let now = new Date(setYear, setMonth - 1)//当前月份的1号
      let startWeek = now.getDay(); //目标月1号对应的星期
      let dayNum = new Date(setYear, setMonth, 0).getDate() //当前月有多少天
      let forNum = Math.ceil((startWeek + dayNum) / 7) * 7 //当前月跨越的周数
      if (this.data.open) {
        //展开状态,需要渲染完整的月份
        for (let i = 0; i < forNum; i++) {
          const now2 = new Date(now)
          now2.setDate(i - startWeek + 1)
          let obj = {};
          obj = {
            day: now2.getDate(),
            month: now2.getMonth() + 1,
            year: now2.getFullYear(),
            dateString: this.formatTime(now2, "Y-M-D")
          };
          dateList[i] = obj;
        }
      } else {
        //非展开状态,只需要渲染当前周
        for (let i = 0; i < 7; i++) {
          const now2 = new Date(now)
          //当前周的7天
          now2.setDate(Math.ceil((this.data.selectDay.day + startWeek) / 7) * 7 - 6 - startWeek + i)
          let obj = {};
          obj = {
            day: now2.getDate(),
            month: now2.getMonth() + 1,
            year: now2.getFullYear(),
            dateString: this.formatTime(now2, "Y-M-D")
          };
          dateList[i] = obj;
        }
      }
      this.setData({
        dateList: dateList
      })
    },
    // 某一天被点击时
    selectChange(e) {
      const year = e.currentTarget.dataset.year
      const month = e.currentTarget.dataset.month
      const day = e.currentTarget.dataset.day
      const dateString = e.currentTarget.dataset.dateString
      const selectDay = {
        year: year,
        month: month,
        day: day,
        dateString: dateString
      }
      if (this.data.selectDay.year !== year || this.data.selectDay.month !== month) {
        this.setMonth(year, month, day)
      } else if (this.data.selectDay.day !== day) {
        this.setData({
          selectDay: selectDay
        });
        // 将修改后的日期-传到父组件
        this.triggerEvent("calendarChange", this.data.selectDay)
      }
    }
  },
  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(),
        dateString: this.formatTime(now, "Y-M-D")
      }
      this.setMonth(selectDay.year, selectDay.month, selectDay.day)
    }
  },
  observers: {
    spot: function (spot) {
      this.setSpot()
    }
  }
})

js 中主要传参:
// 将修改后的日期-传到父组件
this.triggerEvent("calendarChange", this.data.selectDay)

-- 父组件
父组件.wxml:

<!-- 日历 -->
<view class="calendar">
  <calendar bind:calendarChange="calendarChange"></calendar>
</view>

父组件.wxss:

/* 日历 */
.calendar {
  width: 100%;
  background: #fff;
  box-sizing: border-box;
  padding: 40rpx 30rpx;
  margin-bottom: 4rpx;
}

父组件.json:

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

父组件.js:

Page({
  data: {
    calendarVal: '', // 日历-值
  },
  // 日历改变-组件传过来的参数
  calendarChange: function (e) {
    this.setData({
      calendarVal: e.detail.dateString
    })
  },
})

参考地址:https://blog.csdn.net/weixin_44182162/article/details/107854570

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容