小程序滚动日历组件

小程序滚动日历组件

前段时间产品提出这个需求,要求做一个日历容器,并要求是滚动,不能是那种每个月切换的容器,所以我就在网上大概查找了一下类似组件,滚动的容器较少,于是我就自己写了这个组件,以下是大概的js思路,wxml和css就不附上了,每个UI都有不同的想法

  1. 在ready中初始化组件数据
/**
 * @description: 初始化
 */
ready() {
  // 这两个数据是从页面中传过来的,起始时间和结束时间
  // 数组类型 [year, month, day]
  const { endDate, startDate } = this.data
  let monthList = [] // 这个用于wxml中遍历,以每月为item

  // 未跨年
  if ( endDate[0] === startDate[0]) {
    let rangeMonth = endDate[1] - startDate[1]
    for (let i = 0; i <= rangeMonth; i++) {
      let date = [startDate[0], startDate[1] + i + 1]
      // monthInitData()初始化每月数据
      let days = this.monthInitData(startDate[0], startDate[1] + i)
      monthList.push({
        date,
        days,
      })
    }
  } else {
    // 跨年前月份
    for (let i = 0, lng = 12 - startDate[1]; i < lng; i++) {
      let date = [startDate[0], startDate[1] + i + 1]
      let days = this.monthInitData(startDate[0], startDate[1] + i)
      monthList.push({
        date,
        days,
      })
    }

    // 跨年后月份
    for (let i = 0; i <= endDate[1]; i++) {
      let date = [endDate[0], i + 1]
      let days = this.monthInitData(endDate[0], i)
      monthList.push({
        date,
        days,
      })
    }
  }
  this.setData({
    monthList,
  })
}
  1. 初始化每月数据:

逻辑是获取每个月第一天的星期数和每个月的最大天数,然后在之前和之后的空数据填充item占位
然后遍历,根据不同的需求,在遍历中处理,最后在html中flex布局即可

/**
 * @description: 初始化每月数据
 * @param: { number } year 年
 * @param: { number } month 月
 */
monthInitData(year, month) {
  let { calendarValue, startDate, endDate }= this.data, // 当前点击时间,起始时间,结束时间
    firstWeek = new Date(year, month, 1).getDay(), // 本月的第一天的星期数
    days = [], // 日期数组
    max = this.getMonthMax(year, month + 1), // 每月最大天数
    lastWeek = new Date(year, (month + 1), 0).getDay() // 本月的最后一天的星期数

  // 填充每月一号之前的空数据
  if (firstWeek > 0) {
    for (let i = 0; i < firstWeek; i++) {
      days.push({
        day: 0
      })
    }
  }

  let currentTime = 0, 
      startTime = 0,
      endTime = 0

  if (calendarValue[0]) {
    currentTime = new Date(calendarValue[0], calendarValue[1], calendarValue[2]).getTime()
  }
  if (startDate[0]) {
    startTime = new Date(startDate[0], startDate[1], startDate[2]).getTime()
  }
  if (endDate[0]) {
    endTime = new Date(endDate[0], endDate[1], endDate[2]).getTime()
  }

  for (let i = 1; i <= max; i++) {
    // 以下状态是需要在html中判断处理,根据自己需求改变
    let current = false, // 当前点击状态
      disabled = false, // 禁止状态
      now = false, // 今天显示文案
      time = new Date(year, month, i).getTime(),
      nowTime = [new Date().getFullYear(), new Date().getMonth(), new Date().getDate()]
    if (currentTime && currentTime == time) current = true
    if (startTime && startTime > time) disabled = true
    if (endTime && endTime < time) disabled = true
    if (year === nowTime[0] && month === nowTime[1] && i === nowTime[2]) now = true

    days.push({
      day: i,
      current,
      disabled,
      now,
    })
  }

  // 填充每月最后一天之后的空数据
  if (lastWeek != 6) {
    for (let i = 0, l = (6 - lastWeek); i < l; i++) {
      days.push({
        day: 0
      })
    }
  }
  return days
},

/**
 * 获取一个月最大天数
 * @method getMonthMax
 * @param: { number } year 年份
 * @param: { number } month 月份
 */
getMonthMax(year, month) {
  let max = 31
  if (month == 4 || month == 6 || month == 9 || month == 11) {
    max = 30
  } else if (month == 2) {
    if (((year % 4) == 0 && (year % 100) > 0) || (year % 400) == 0) {
      max = 29
    } else {
      max = 28
    } 
  }

  return max
},

  • 以上就是核心逻辑,像一些弹窗事件和一些点击事件就不附上来了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值