小程序修改时间选择器组件

4 篇文章 1 订阅
2 篇文章 0 订阅

目的:
在实际开发中,小程序提供的picker时间选择器无法修改样式,这可能与项目整体的风格不一致,因此借助小程序picker-view实现自定义样式的时间选择器
功能:
支持默认时间,初始值是当天,根据选择的不同年月日限制可选值(因为大小月平年闰年天数不一样)

readme

Props
defaultValue:string(2019-10-15)
默认值:当前时间
Events

cancel:Function
说明:取消时触发
参数:null

confirm:Function
说明:确定时触发
参数:event.detail选中的时间

直接将下面代码复制即可直接使用
js

// components/date_time_picker/index.js
const years = [];
const months = [];
const days = [];
const date = new Date(new Date().getTime() + 24 * 3600 * 1000);
const currentYear = date.getFullYear();
const currentMonth = date.getMonth() + 1;
const currentDay = date.getDate();

// 根据年和月获取当月天数
function getDayNum(year, month) {
  return new Date(year, month, 0).getDate();
}

for (let i = currentYear; i <= 2099; i++) {
  years.push(i);
}

for (let i = currentMonth; i <= 12; i++) {
  months.push(i);
}

for (let i = currentDay; i <= getDayNum(currentYear, currentMonth); i++) {
  days.push(i);
}

let selectedYear = currentYear;
let selectedMonth = currentMonth;
let selectedDay = currentDay;

Component({
  ready() {
    let timeArr = this.data.defaultValue.split('-').map(i => Number(i));
    selectedYear = timeArr[0];
    selectedMonth = timeArr[1];
    selectedDay = timeArr[2];

    let months = [];
    let days = [];
    let monthStartFlag = 1;
    let monthEndFlag = 12;
    let dayStartFlag = 1;
    let datEndFlag = getDayNum(timeArr[0], timeArr[1]);

    if (timeArr[0] === currentYear) {
      monthStartFlag = currentMonth;
    }
    if (timeArr[0] === currentYear && timeArr[1] === currentMonth) {
      dayStartFlag = currentDay;
    }

    for (let i = monthStartFlag; i <= monthEndFlag; i++) {
      months.push(i);
    }
    for (let i = dayStartFlag; i <= datEndFlag; i++) {
      days.push(i);
    }

    this.setData({
      months,
      days
    });

    let yearIndex = this.data.years.indexOf(timeArr[0]);
    let monthIndex = this.data.months.indexOf(timeArr[1]);
    let dayIndex = this.data.days.indexOf(timeArr[2]);
    this.setData({
      yearDefaultIndex: yearIndex,
      monthDefaultIndex: monthIndex,
      dayDefaultIndex: dayIndex
    });
  },

  properties: {
    defaultValue: {
      type: String,
      value: `${currentYear}-${currentMonth}-${currentDay}`
    }
  },

  data: {
    years,
    months,
    days,
    yearDefaultIndex: null,
    monthDefaultIndex: null,
    dayDefaultIndex: null
  },

  methods: {
    pickerChange: function(ev) {
      let _this = this;
      let index = ev.detail.value[0];
      let type = ev.target.dataset.type;
      let typeMap = {
        year: function(index) {
          let year = _this.data.years[index];
          console.log(year, '年');
          selectedYear = year;

          // 设置月
          let monthStartFlag = 1;
          let months = [];
          if (year === currentYear) {
            monthStartFlag = currentMonth;

            let monthIndex = null;
            let dayIndex = null;

            if (selectedMonth <= currentMonth) {
              selectedMonth = currentMonth;
              monthIndex = 0;
              if (selectedDay < currentDay) {
                selectedDay = currentDay;
                dayIndex = 0;
              } else {
                dayIndex = selectedDay - currentDay;
              }
            } else {
              monthIndex = selectedMonth - currentMonth;
              dayIndex = selectedDay - 1;
            }

            _this.setData({
              monthDefaultIndex: monthIndex,
              dayDefaultIndex: dayIndex
            });
          } else {
            setTimeout(() => {
              _this.setData({
                monthDefaultIndex: selectedMonth - 1,
                dayDefaultIndex: selectedDay - 1
              });
            }, 0);
          }
          for (let i = monthStartFlag; i <= 12; i++) {
            months.push(i);
          }
          _this.setData({
            months
          });

          // 设置日
          let dayStartFlag = 1;
          let days = [];
          let dayEndFlag = getDayNum(selectedYear, selectedMonth);
          if (selectedYear === currentYear && selectedMonth === currentMonth) {
            dayStartFlag = currentDay;
          }
          for (let i = dayStartFlag; i <= dayEndFlag; i++) {
            days.push(i);
          }
          _this.setData({
            days
          });
        },
        month: function(index) {
          let month = _this.data.months[index];
          console.log(month, '月');
          selectedMonth = month;
          let dayStartFlag = 1;
          let days = [];
          let dayEndFlag = getDayNum(selectedYear, selectedMonth);
          if (selectedYear === currentYear && selectedMonth === currentMonth) {
            dayStartFlag = currentDay;

            selectedMonth = currentMonth;
            selectedDay = currentDay;

            _this.setData({
              monthDefaultIndex: 0,
              dayDefaultIndex: 0
            });
          } else {
            let selectedDayIndex = selectedDay - 1;
            setTimeout(() => {
              if (selectedDayIndex >= _this.data.days.length) { // 大月最后一天会大于小月
                selectedDayIndex = _this.data.days.length - 1;
                selectedDay = _this.data.days.slice(-1)[0];
              }
              _this.setData({
                dayDefaultIndex: selectedDayIndex
              });
            }, 0);
          }
          for (let i = dayStartFlag; i <= dayEndFlag; i++) {
            days.push(i);
          }
          _this.setData({
            days
          });
        },
        day: function(index) {
          let day = _this.data.days[index];
          console.log(day, '日');
          selectedDay = day;
        }
      };
      typeMap[type](index);
    },
    cancelAction: function() {
      this.triggerEvent('cancel');
    },
    confirmAction: function() {
      let year = selectedYear;
      let month = selectedMonth;
      let day = selectedDay;
      if (month < 10) {
        month = '0' + month;
      }
      if (day < 10) {
        day = '0' + day;
      }
      this.triggerEvent('confirm', `${year}-${month}-${day}`);
    }
  }
});

wxml

<!--components/date_time_picker/index.wxml-->
<view class="picker-wrapper">

<view class="picker-toolbar border-bottom">
      <text class="cancel" catch:tap="cancelAction">取消</text>
      <text class="confirm" catch:tap="confirmAction">确定</text>
</view>

<view class="picker-item-wrapper">

 <picker-view value="{{[yearDefaultIndex]}}" class="picker-item-year" indicator-style="height: 40px;" bindchange="pickerChange" data-type="year">
      <picker-view-column>
        <view wx:for="{{years}}" wx:key="index" class="picker-item-value">{{item}}年</view>
      </picker-view-column>
</picker-view>

 <picker-view value="{{[monthDefaultIndex]}}" class="picker-item-month" indicator-style="height: 40px;" bindchange="pickerChange" data-type="month">
      <picker-view-column>
        <view wx:for="{{months}}" wx:key="index" class="picker-item-value">{{item}}月</view>
      </picker-view-column>
</picker-view>

 <picker-view value="{{[dayDefaultIndex]}}" class="picker-item-day" indicator-style="height: 40px;" bindchange="pickerChange" data-type="day">
      <picker-view-column>
        <view wx:for="{{days}}" wx:key="index" class="picker-item-value">{{item}}日</view>
      </picker-view-column>
</picker-view>

</view>

</view>

/* components/date_time_picker/index.wxss */
@keyframes popupTitle {
  from {
    bottom: 0;
  }

  to {
    bottom: 40%;
  }
}

@keyframes popup {
  from {
    bottom: -40%;
  }

  to {
    bottom: 0rpx;
  }
}

.picker-wrapper {
  z-index: 999;
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.7);
}

.picker-wrapper .picker-toolbar {
  background-color: white;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 48px;
  display: flex;
  align-items: center;
  font-size: 32rpx;
  justify-content: space-between;
  padding: 0 32rpx;
  animation: popupTitle 0.4s normal forwards;
}

.picker-wrapper .picker-toolbar .confirm {
  color: #006EFF;
}

.picker-wrapper .picker-item-wrapper {
  display: flex;
  background-color: white;
  position: absolute;
  right: 0;
  bottom: -40%;
  left: 0;
  height: 40%;
  animation: popup 0.4s normal forwards;
}

.picker-wrapper .picker-item-year,
.picker-item-month,
.picker-item-day {
  flex: 1;
}

.picker-wrapper .picker-item-year,
.picker-item-month,
.picker-item-day .picker-item-value {
  text-align: center;
  line-height: 40px;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值