学无先后,达者为师

网站首页 编程语言 正文

小程序自定义日期组件,不显示今日之后的日期

作者:ZionHH 更新时间: 2022-05-12 编程语言

官方picker可以设置有效时间,有效时间外的禁止选择,但是无法隐藏,于是决定通过picker-viewpicker-view-column来手写一个,效果如图:
在这里插入图片描述
需要注意的一些地方:

  1. 2月份,需要判断是平/闰年;
  2. 大小月,30或31天;
  3. 还有就是选择本年,控制显示月份,选择本月控制显示日。

组件 wxml

<slot bindtap="handlePicker">slot>
  
<view hidden="{{!visible}}" class="date-picker-cover" bindtap="tapCancel">view>
<view class="date-picker" animation="{{animationData}}">
    <view class="btn-area">
      <view class="btn-cancel" bindtap="tapCancel">取消view>
      <view class="btn-confirm" bindtap="tapConfirm">确定view>
    view>
    <picker-view class="picker-view" value="{{value}}" bindchange="changeDate">
      <picker-view-column>
          <view wx:for="{{years}}" wx:key="index" class="picker-view-column">{{item}}年view>
        picker-view-column>
      <picker-view-column>
          <view wx:for="{{showDate.months}}" wx:key="index" class="picker-view-column">{{item > 9 ? item : '0' + item}}月view>
        picker-view-column>
      <picker-view-column>
          <view wx:for="{{showDate.days}}" wx:key="index" class="picker-view-column">{{item > 9 ? item : '0' + item}}日view>
        picker-view-column>
    picker-view>
  view>

组件 js

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    // 日期 格式 yyyy-MM-DD
    dateValue: {
      type: String,
      observer: function (val) {
        if (val) {
          this.initDate(val)
        }
      }
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    visible: false,
    years: [],
    curDate: {
      year: null,
      month: null,
      day: null
    },
    // 全部月、日
    fullDate: {
      months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
      days: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
    },
    // 显示月、日
    showDate: {
      months: [],
      days: []
    },
    value: null,
    dateArr: null,
    formatDate: '',
    animate: null,
    animationData: null
  },
  pageLifetimes: {
    show() {
      let animate = wx.createAnimation({
        duration: 400,
        timingFunction: 'ease',
      })
      this.setData({
        animate
      })
    }
  },
  /**
   * 组件的方法列表
   */
  methods: {
    // 选择日期
    handlePicker() {
      const slideUp = this.data.animate.bottom(0).step()
      this.setData({
        animationData: slideUp.export(),
        // 弹出日期时,显示确定的时间
        value: this.data.value,
        visible: true
      })
    },
    // 初始化日期
    initDate(val) {
      const date = new Date()
      const curDate = {
        year: date.getFullYear(),
        month: date.getMonth() + 1,
        day: date.getDate()
      }
      
      let years = []
      for (let i = 1; i <= curDate.year; i++) {
        years.push(i)
      }
      const value = val.split('-')
      this.setData({
        years,
        curDate,
        value: value.map(item => Number(item) - 1)
      })
      this.computedDate(value)
    },
    // 选择日期
    changeDate(val) {
      let value = val.detail.value.map(item => item + 1)
      this.computedDate(value)
      const month = value[1] > 9 ? value[1] : '0' + value[1]
      const day = value[2] > 9 ? value[2] : '0' + value[2]
      this.setData({
        dateArr: val.detail.value,
        formatDate: `${value[0]}-${month}-${day}`,
      })
    },
    // 计算月、日
    computedDate (val) {
      const { months: fullMonths, days: fullDays } = this.data.fullDate
      const year = Number(val[0])
      const month = Number(val[1])
      // 闰年:能被 4 整除并且不能被 100 整除,或者被 400 整除
      const leapYear = !(year % 4) && (year % 100) || !(year % 400) ? true : false
      // 默认大月 0:2月 1:小月
      let monthType = null
      if (month === 2) {
        monthType = 0
      } else if ([4, 6, 9, 11].includes(month)) {
        monthType = 1
      }

      // 本年显示 ≤ 本月
      let months = year === this.data.curDate.year ? fullMonths.slice(0, this.data.curDate.month) : fullMonths

      let days = fullDays
      if (year === this.data.curDate.year && month === this.data.curDate.month) {
        // 本年且本月,显示 ≤ 本日
        days = fullDays.slice(0, this.data.curDate.day)
      } else {
        if (monthType === 0) {
          // 2月
          days = leapYear ? fullDays.slice(0, 29) : fullDays.slice(0, 28)
        } else if (monthType === 1) {
          // 小月
          days = fullDays.slice(0, 30)
        }
      }
      this.setData({
        ['showDate.months']: months,
        ['showDate.days']: days
      })
    },
    // 确定
    tapConfirm() {
      const slideDown = this.data.animate.bottom('-560rpx').step()
      this.triggerEvent('change', this.data.formatDate)
      this.setData({
        value: this.data.dateArr,
        animationData: slideDown.export(),
        visible: false
      })
    },
    // 取消
    tapCancel() {
      const slideDown = this.data.animate.bottom('-560rpx').step()
      this.setData({
        animationData: slideDown.export(),
        visible: false
      })
    }
  }
})

组件 wxss

.date-picker-cover {
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, .5);
  position: fixed;
  top: 0;
  left: 0;
  z-index: 99;
}
.date-picker {
  width: 100%;
  position: absolute;
  left: 0;
  bottom: 0;
  background-color: #fff;
  position: fixed;
  bottom: -560rpx;
  left: 0;
  z-index: 100;
}
.date-picker .btn-area {
  box-sizing: border-box;
  width: 100%;
  display: flex;
  justify-content: space-between;
  padding: 18rpx 30rpx;
  border-bottom: 2rpx solid #f6f6f6;
  font-size: 32rpx;
}
.date-picker .btn-area .btn-cancel {
  color: #7f7f7f;
}
.date-picker .btn-area .btn-confirm {
  color: #07c160;
}
.date-picker .picker-view {
  width: 100%;
  height: 480rpx;
}
.date-picker .picker-view .picker-view-column {
  line-height: 34px;
  text-align: center;
  font-size: 32rpx;
}

调用组件


<view>
  <date-picker dateValue="{{date}}" bindchange="changeDate">
    <view class="date-content">选择日期:{{date}}view>
  date-picker>
view>
// js
Page({
  data: {
    date: '2021-12-02'
  },
  onLoad() {
  },
  changeDate(val) {
    this.setData({
      date: val.detail
    })
  }
})
// json
{
  "usingComponents": {
    "date-picker": "/components/date-picker/date-picker"
  }
}

原文链接:https://blog.csdn.net/z291493823/article/details/122516359

栏目分类
最近更新