微信小程序原生写法——24小时时间选择器组件

  • Post author:
  • Post category:小程序


使用picker-view来封装成的一个时间选择器

开始时间是当前时间的一个小时之后,秒默认是0秒

在这里插入图片描述

可能还有一些情况未处理,后续发现再更新

js文件

第一版:略繁琐

// components/pickerTime/pickerTime.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {},

  /**
   * 组件的初始数据
   */
  data: {
    years: [], //年-月列表
    days: [], //日期列表
    hours: [], //小时列表
    minutes: [], //分支列表
    pickerTime: [0, 0, 0, 0], //列表选定的列集合
    timeRegion: "", //选定的时间字符串
    hList1: [], //未满24小时(第一天的小时列表)
    hList2: [], //完整24小时(第二天的小时列表)
    mList1: [], //第一个小时的分钟列表(不一定满60分钟)
    mList2: [], //满60分钟
    mList3: [], //最后一小时的分钟列表(不一定满60分钟)
    dList: [], //日期列表(最多有两个)
    yList: [], //年/月列表(最多有两个)
    yTime: 0, //已选年-月索引
    dTime: 0, //已选日期索引
    hTime: 0, //已选小时索引
    mTime: 0, //已选分钟索引
    isNext: false, //是否跨年/月
  },
  lifetimes: {
    attached: function () {
      // 在组件实例进入页面节点树时执行
      this.handleTime();
    },
  },
  /**
   * 组件的方法列表
   */
  methods: {
    // 处理时间
    handleTime() {
      // 日期
      const dList = this.handleD();
      console.log(dList, 121212);
      // 小时
      const hList = this.handleH();
      console.log(hList, 11111);
      // 分钟
      const mList = this.handleM();
      console.log(mList, 3333);
      this.handleTimeRegion();
    },
    // 获取当前月有多少天
    getMonth(date) {
      let dt = new Date(date);
      const month = dt.getMonth();
      dt.setMonth(month + 1);
      dt.setDate(0);
      return dt.getDate();
    },
    // 处理分钟列表
    handleM() {
      // 分钟列表
      let mList1 = [],
        mList2 = [],
        mList3 = []; //分钟列表
      const date = new Date();

      // 获取分钟列表
      let M = date.getMinutes(); //获取当前分钟数(0-59)
      let H = date.getHours() + 1; //获取当前小时数(0-23)
      // H = 23;
      // M = 0;
      // 到60分还剩多少分钟
      let surplusM = 60 - M;
      for (let i = 0; i < surplusM + 1; i++) {
        let mm = M + i;
        if (mm < 60) {
          mm = mm < 10 ? "0" + mm : mm;
          mList1.push(mm);
        }
      }
      //完整60分钟
      for (let i = 0; i < 60; i++) {
        const mm = i < 10 ? "0" + i : i;
        mList2.push(mm);
      }
      // 判断当前是00分时,最后一个小时是00-59分
      if (M == 0) {
        M = 60;
      }
      // 最后一小时的分钟
      for (let i = 0; i < M; i++) {
        const mm = i < 10 ? "0" + i : i;
        mList3.push(mm);
      }
      this.setData({
        mList1,
        mList2,
        mList3,
        minutes: mList1,
      });
      return [mList1, mList2, mList3];
    },
    // 处理小时列表
    handleH() {
      // 小时列表
      let hList1 = [],
        hList2 = []; //小时列表
      const date = new Date();
      // 获取小时列表
      let H = date.getHours() + 1; //获取当前小时数(0-23)
      let M = date.getMinutes(); //获取当前分钟数(0-59)
      // M = 0;
      // H = 23;
      // 到24点还剩多少小时
      let surplusH = 24 - H;
      // 当前是零点,小时+1
      if (H == 0) {
        H++;
      }
      for (let i = 0; i < surplusH; i++) {
        let hh = H + i;
        if (hh < 24) {
          hh = hh < 10 ? "0" + hh : hh;
          hList1.push(hh);
        }
      }
      // 第二天剩余的小时
      for (let i = 0; i < H; i++) {
        const hh = i < 10 ? "0" + i : i;
        hList2.push(hh);
      }
      // 判断当前是00分时,第二天要去掉最后一个的一个小时
      if (M == 0) {
        hList2.pop();
      }
      // 判断当前是23点的,hList2添加23点的数据,hList1与hList2一致
      if (H == 23) {
        hList2.push(23);
        hList1 = hList2;
      }
      this.setData({
        hList1,
        hList2,
        hours: H == 23 ? hList2 : hList1,
      });
      return [hList1, hList2];
    },
    // 处理日期列表
    handleD() {
      const date = new Date();
      let YY = date.getFullYear(); //获取完整的年份(4位,1970-???)
      let isNext = false; //是否跨月/年
      let MM = date.getMonth() + 1; //获取当前月份(0-11,0代表1月),
      let H = date.getHours(); //获取当前小时数(0-23)
      let M = date.getMinutes(); //获取当前分钟数(0-59)

      // H = 23;
      MM = MM < 10 ? "0" + MM : MM;
      // 返回当月有多少天
      const allM = this.getMonth(YY + "-" + MM + "-" + "01");
      // 获取日期列表
      let DD = date.getDate(); //获取当前日(1-31)
      const DDD = DD < 10 ? "0" + DD : DD;
      let dList = [DDD];
      let yList = [`${YY}-${MM}`];
      // 判断是否是零点零分
      let isZero = H == 0 && M == 0;
      // 不是零点零分,就跨天,添加第二天
      if (!isZero) {
        // 当天是否是最后一天,最后一天+1,就到下一个月的1号
        let dd = DD + 1 > allM ? 1 : DD + 1;
        dd = dd < 10 ? "0" + dd : dd;
        dList.push(dd);
      }
      // DD = 31;
      // MM = 12;

      // 判断第二天是下个月的第一天,月份+1,(不是12月)
      if (DD + 1 > allM && MM != 12 && !isZero) {
        MM = Number(MM) + 1;
        yList.push(`${YY}-${MM < 10 ? "0" + MM : MM}`);
        isNext = true;
      } else if (MM == 12 && DD + 1 > allM && !isZero) {
        // 是12月份,并且是31号,年份+1,月份改为1月份
        YY = YY + 1;
        MM = "01";
        isNext = true;
        yList.push(`${YY}-${MM}`);
      }
      // 判断是否是23点,日期列表dList删除第一个,isNext为false,不跨年/月
      if (H == 23 && dList.length > 1) {
        dList.shift();
        isNext = false;
        // 判断如果有跨年/月的,有的话删除yList第一个
        if (yList.length > 1) {
          yList.shift();
        }
      }
      const days = isNext ? [dList[0]] : dList;
      this.setData({
        dList,
        days,
        years: yList,
        yList,
        isNext,
      });
      return dList;
    },
    // 切换处理
    bindChange({ detail }) {
      console.log(detail, 2222);
      const data = detail.value;
      // 索引
      let yTime = this.data.yTime;
      let dTime = this.data.dTime;
      let hTime = this.data.hTime;
      let mTime = data[3];
      // 第一个小时
      let isFirst = true;
      // 最后一个小时
      let isLast = false;
      // 年/月切换
      if (data[0] != this.data.yTime) {
        yTime = data[0];
        dTime = 0;
        hTime = 0;
        mTime = 0;
      }
      // 日期切换
      if (data[1] != this.data.dTime) {
        dTime = data[1];
        hTime = 0;
        mTime = 0;
      }
      // 小时切换
      if (data[2] != this.data.hTime) {
        hTime = data[2];
        mTime = 0;
      }
      // 分钟切换
      if (data[3] != this.data.mTime) {
        mTime = data[3];
      }
      // 是否是第一个小时
      isFirst = dTime == 0 && hTime == 0;
      // 是否是最后一个小时
      isLast =
        dTime == this.data.days.length - 1 &&
        hTime == this.data.hours.length - 1;
      let noNextM = true;
      //当选择第二个月份日期
      if (data[0] == 1) {
        noNextM = false;
        // 设置不是第一个小时
        isFirst = false;
        // 判断小时是否切换
        if (data[2] != this.data.hTime) {
          // 判断是不是最后一个小时,不是最后一个小时,分钟列表是满60
          isFirst = data[2] != this.data.hours.length - 1;
        }
        // 判断是否是最后一个钟
        isLast = hTime == this.data.hours.length - 1;
      }
      // 判断是否只有一个月份
      const isYears = this.data.years.length == 1;
      // days:判断是否是只有一个月份,只有一个月份,值为整个dList;若有两个月份的,则再判断选择了第一个月份(值为dList的第一个元素)还是第二个月份(值为dList的第二个元素)
      // hours:先判断是不是选的第二个月份以及是否是第一天
      // minutes:第一天的第一个小时(值为mList1),第二天的最后一个小时(值为mList3),其他中间时间为mList2
      this.setData({
        days: isYears
          ? this.data.dList
          : yTime == 0
          ? [this.data.dList[0]]
          : [this.data.dList[1]],
        hours: dTime == 0 && noNextM ? this.data.hList1 : this.data.hList2,
        minutes: isFirst
          ? this.data.mList1
          : isLast
          ? this.data.mList3
          : this.data.mList2,
        pickerTime: [yTime, dTime, hTime, mTime],
        yTime,
        dTime,
        hTime,
        mTime,
      });
      this.handleTimeRegion();
    },
    // 处理最后生成的pickerTime字符串
    handleTimeRegion() {
      const data = this.data.pickerTime;
      const y = this.data.years[data[0]];
      const d = this.data.days[data[1]];
      const h = this.data.hours[data[2]];
      const m = this.data.minutes[data[3]];
      const timeRegion = y + "-" + d + " " + h + ":" + m + ":" + "00";
      this.setData({
        timeRegion,
      });
    },
    // 取消
    onCancel() {
      const obj = {
        timeRegion: "",
        isPicker: false,
      };
      this.triggerEvent("onselect", obj);
    },
    // 确认
    onChecking() {
      const obj = {
        timeRegion: this.data.timeRegion,
        isPicker: true,
      };
      this.triggerEvent("onselect", obj);
    },
  },
});

第二版js文件:根据当前时间的时间戳A与24小时之后的时间戳B两者来进行处理获取对应的列表

// components/pickerTime/pickerTime.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {},

  /**
   * 组件的初始数据
   */
  data: {
    years: [], //年-月列表
    days: [], //日期列表
    hours: [], //小时列表
    minutes: [], //分支列表
    pickerTime: [0, 0, 0, 0], //列表选定的列集合
    timeRegion: "", //选定的时间字符串
    hList1: [], //未满24小时(第一天的小时列表)
    hList2: [], //完整24小时(第二天的小时列表)
    mList1: [], //第一个小时的分钟列表(不一定满60分钟)
    mList2: [], //满60分钟
    mList3: [], //最后一小时的分钟列表(不一定满60分钟)
    dList: [], //日期列表(最多有两个)
    yList: [], //年/月列表(最多有两个)
    yTime: 0, //已选年-月索引
    dTime: 0, //已选日期索引
    hTime: 0, //已选小时索引
    mTime: 0, //已选分钟索引
    hList: [], //所有小时列表(24)
  },
  lifetimes: {
    attached: function () {
      // 在组件实例进入页面节点树时执行
      this.handleTime();
    },
  },
  /**
   * 组件的方法列表
   */
  methods: {
    // 处理时间
    handleTime() {
      this.getPastTime();
      this.handleTimeRegion();
    },
    // 切换处理
    bindChange({ detail }) {
      console.log(detail, 2222);
      const data = detail.value;
      // 索引
      let yTime = this.data.yTime;
      let dTime = this.data.dTime;
      let hTime = this.data.hTime;
      let mTime = 0;
      let minutes = this.data.minutes;
      let hours = this.data.hours;
      // 年/月切换
      // 只有跨月(跨年)才会有机会切换
      if (data[0] != this.data.yTime) {
        yTime = data[0];
        // 如跨月(跨年)第一个日期是上个月的,第二个日期是下个月的
        dTime = data[0];
        hTime = 0;
        mTime = 0;
        // 如果是第一天,小时列表为hList1,否则为hList2
        hours = dTime == 0 ? this.data.hList1 : this.data.hList2;
        minutes = dTime == 0 ? this.data.mList1 : this.data.mList3;
      }
      // 日期切换
      if (data[1] != this.data.dTime) {
        dTime = data[1];
        hTime = 0;
        mTime = 0;
        // 如果有跨月/年,年月和日要同步
        if (this.data.yList.length > 1) {
          yTime = data[1];
        }
        // 如果是第一天,小时列表为hList1,否则为hList2
        hours = data[1] == 0 ? this.data.hList1 : this.data.hList2;
        minutes = data[1] == 0 ? this.data.mList1 : this.data.mList3;
      }
      // 小时切换
      if (data[2] != this.data.hTime) {
        // 切换到第一天的第一个小时
        if (data[0] == 0 && data[1] == 0 && data[2] == 0) {
          minutes = this.data.mList1;
        } else if (
          data[0] == this.data.yList.length - 1 &&
          data[1] == 1 &&
          data[2] == this.data.hList2.length - 1
        ) {
          // 第二天的最后一个小时
          minutes = this.data.mList2;
        } else {
          // 中间小时
          minutes = this.data.mList3;
        }
        hTime = data[2];
        mTime = 0;
      }
      // 分钟切换
      if (data[3] != this.data.mTime) {
        mTime = data[3];
      }
      this.setData({
        days: this.data.dList,
        hours,
        minutes,
        pickerTime: [yTime, dTime, hTime, mTime],
        yTime,
        dTime,
        hTime,
        mTime,
      });
      this.handleTimeRegion();
    },
    getPastTime() {
      // 获取24小时之后的时间戳
      const nextTime = new Date().getTime() + 24 * 60 * 60 * 1000;
      // 一个小时之后的时间戳
      const currentTime = new Date().getTime() + 60 * 60 * 1000;
      // 处理年月
      this.getYM(currentTime, nextTime);
      // 处理日
      this.getDay(currentTime, nextTime);
      // 处理小时
      this.getHour(currentTime, nextTime);
      // 处理分钟
      this.getMinute(currentTime, nextTime);
    },
    // 获取年月列表
    getYM(currentTime, nextTime) {
      const yTime1 = this.timeFormat(currentTime, "getFullYear");
      const yTime2 = this.timeFormat(nextTime, "getFullYear");
      let mTime1 = this.timeFormat(currentTime, "getMonth");
      let mTime2 = this.timeFormat(nextTime, "getMonth");
      const resStr1 = yTime1 + "-" + mTime1;
      const resStr2 = yTime2 + "-" + mTime2;
      // 去重处理
      const yList = Array.from(new Set([resStr1, resStr2]));
      this.setData({
        years: yList,
        yList,
      });
      console.log("yList:", yList);
    },
    // 获取日期
    getDay(currentTime, nextTime) {
      let dTime1 = this.timeFormat(currentTime, "getDate");
      let dTime2 = this.timeFormat(nextTime, "getDate");
      // 去重处理
      const dList = Array.from(new Set([dTime1, dTime2]));
      this.setData({
        dList,
        days: dList,
      });
      console.log("dList:", dList);
    },
    // 获取小时列表,整点需要处理
    getHour(currentTime, nextTime) {
      let workTime = currentTime;
      let hList1 = [],
        hList2 = [],
        hList = [];
      // 第一天的日期
      const day1 = this.timeFormat(currentTime, "getDate");
      while (workTime <= nextTime) {
        let H = this.timeFormat(workTime, "getHours"); //获取当前小时数(0-23)
        // 第二天的日期
        const day2 = this.timeFormat(workTime, "getDate");
        if (day1 == day2) {
          hList1.push(H);
        } else {
          hList2.push(H);
        }
        hList.push(H);
        workTime = workTime + 3600000;
      }
      // 获取分钟
      let M = this.timeFormat(currentTime, "getMinutes"); //获取当前分钟数(0-59)
      // 判断如果是整点,就去掉最后一个小时
      if (M == "00") {
        hList2.splice(hList2.length - 1);
      }
      this.setData({
        hList1,
        hList2,
        hList,
        hours: hList1,
      });
      console.log("hList:", [hList1, hList2]);
    },
    // 获取分钟列表
    getMinute(currentTime, nextTime) {
      let workTime = currentTime;
      let mList1 = [],
        mList2 = [],
        mList3 = [];
      while (workTime <= nextTime) {
        // 获取小时
        let H = this.timeFormat(workTime, "getHours"); //获取当前小时数(0-23)
        // 获取分钟
        let M = this.timeFormat(workTime, "getMinutes"); //获取当前分钟数(0-59)
        if (H == this.data.hList[0]) {
          // 第一个小时
          mList1.push(M);
        } else if (
          H == this.data.hList[this.data.hList.length - 1] &&
          M != "00"
        ) {
          //最后一个小时(不是整点,不满一个小时)
          mList2.push(M);
        } else if (
          H == this.data.hList[this.data.hList.length - 1] &&
          M == "00"
        ) {
          //最后一个小时(整点,满一个小时)
          mList2.push(M);
        }
        workTime = workTime + 60000;
      }
      // 获取满一个小时的分钟数
      for (let i = 0; i < 60; i++) {
        const M = i > 9 ? i : "0" + i;
        mList3.push(M);
      }
      this.setData({
        mList1,
        mList2,
        mList3,
        minutes: mList1,
      });
      console.log("mList:", [mList1, mList2, mList3]);
    },
    //时间生成并加0处理
    timeFormat(time, type) {
      let resTime = new Date(time)[type]();
      // 获取月份的要+1
      resTime = type == "getMonth" ? resTime + 1 : resTime;
      // 小于10,前面加0
      resTime = resTime > 9 ? resTime : "0" + resTime;
      return resTime;
    },
    // 处理最后生成的pickerTime字符串
    handleTimeRegion() {
      const data = this.data.pickerTime;
      const y = this.data.years[data[0]];
      const d = this.data.days[data[1]];
      const h = this.data.hours[data[2]];
      const m = this.data.minutes[data[3]];
      const timeRegion = y + "-" + d + " " + h + ":" + m + ":" + "00";
      this.setData({
        timeRegion,
      });
    },
    // 取消
    onCancel() {
      const obj = {
        timeRegion: "",
        isPicker: false,
      };
      this.triggerEvent("onselect", obj);
    },
    // 确认
    onChecking() {
      const obj = {
        timeRegion: this.data.timeRegion,
        isPicker: true,
      };
      this.triggerEvent("onselect", obj);
    },
  },
});


json文件

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

wxml文件

<!-- components/pickerTime/pickerTime.wxml -->
<!-- 选择未来24小时之内的时间点,打开默认选当前时间一个小时后的时间 -->
<view class="picker-body">
  <view class="show-time">选定的时间:{{timeRegion}}</view>
  <picker-view indicator-style="height: 40px;" style="width: 100%; height: 160px;" value="{{pickerTime}}" bindchange="bindChange">
    <picker-view-column>
      <view wx:for="{{years}}" wx:key="item" style="line-height: 40px; text-align: center;">
        {{item}}
      </view>
    </picker-view-column>
    <picker-view-column>
      <view wx:for="{{days}}" wx:key="item" style="line-height: 40px; text-align: center;">
        {{item}}</view>
    </picker-view-column>
    <picker-view-column>
      <view wx:for="{{hours}}" wx:key="item" style="line-height: 40px; text-align: center;">
        {{item}}</view>
    </picker-view-column>
    <picker-view-column>
      <view wx:for="{{minutes}}" wx:key="item" style="line-height: 40px; text-align: center;">
        {{item}}</view>
    </picker-view-column>
  </picker-view>
  <view class="btnBox">
    <button class='myBtn cancel' style="width: 40%;" bindtap="onCancel">取消</button>
    <button class='myBtn checking' style="width: 40%;" bindtap="onChecking">完 成</button>
  </view>
</view>

wxss文件

/* components/pickerTime/pickerTime.wxss */
.btnBox {
  width: 100%;
  display: flex;
  justify-content: space-around;
  align-items: center;
  background-color: #fff;
  margin-top: 20rpx;
}
.myBtn {
  color: #fff;
  font-weight: normal;
  border-radius: 50rpx;
  margin: 0;
}
.cancel {
  background-color: #fff;
  color: #444;
  border: 2rpx solid #a5a3a3;
}
.checking {
  background-color: #3f74ee;
}
.picker-body {
  width: 100%;
  height: 400rpx;
  position: fixed;
  bottom: 300rpx;
  background-color: #fff;
  border-top: 2rpx solid #999;
  z-index: 999;
}
.show-time {
  width: 100%;
  height: 100rpx;
  text-align: center;
  line-height: 100rpx;
  color: #333;
}

页面引用

//json
{
  "usingComponents": {
    "pickerTime":"../../../components/pickerTime/pickerTime"

  },
}
//wxml
<!-- 选择时间 -->
<pickerTime bind:onselect="onselect" wx:if="{{openPicker}}" />
//js
data: {
    openPicker: true,//打开组件
    timeRegion:'',//选定的时间字符串
  },
  // 确认时间
  onselect({ detail }) {
    this.setData({
      timeRegion: detail.timeRegion || this.data.timeRegion,
      openPicker: false,
    });
  },



版权声明:本文为h_jQuery原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。