微信小程序实现日期时间筛选器

开发微信小程序过程中,有个需求需要用到日期时间筛选器,查看微信官方文档后,发现官方文档的picker筛选器只能单独支持日期或者是时间,所以为了实现需求自己参考企业微信封装了个日期时间筛选器组件。

原理

筛选器的实现,我参考的是小程序官方方式,通过半屏弹窗(mp-half-screen-dialog)结合picker_view进行日期、时间的选择,最终在选择时间后,通过事件触发返回一个change事件,其中参数值为毫秒级时间戳。

实现

1.弹窗的显隐:

在组件的 properties 中传入一个 show 字段,用于控制弹窗的显隐;默认值为 false

2.筛选器类型:

为了更好的兼容性,提供一个 type 字段,用于控制筛选器的所支持 可选择日期 的走向(往前、往后、前后都支持);默认值为 center(前后都支持)。

3.时间区间(年):

year 字段用于控制筛选器的年维度时间区间范围;默认值为 1。

4.时间区间(月):

month 字段用于控制筛选器的月维度时间区间范围。默认值为 ‘undefined’****(声明’month’ 不为undefined时 year失效)。

具体思路:整体思路是监听弹窗的显隐(show),当弹窗显示时,获取对应配置项(类型、年、月)计算对应筛选器的范围,并初始化默认日期时间为当前年月日时分

以下是效果图以及具体代码实现:

wxml代码

<mp-half-screen-dialog show="{{ show }}" maskClosable="{{ true }}" closabled="{{ false }}" extClass="f-date-dialog" catchtouchmove="preventTouchMove" bindclose="bindclose">
  <view slot="desc" class="flex column full-width full-height">
    <view class="bd flex full-width">
      <!-- 日期 -->
      <view class="flex1 flex column align-items-center">
        <picker-view indicator-style="height: 50px;" mode="selector" value="{{ [dateIndex] }}" class="selector__picker" bindchange="dateChange">
          <picker-view-column>
            <view wx:for="{{ dateArr }}" wx:key="index" style="line-height: 50px" class="text-center {{ item.name.length < 10 ? 'h4' : 'h6' }}">{{ item.name }}</view>
          </picker-view-column>
        </picker-view>
      </view>
      <!-- 小时 -->
      <view class="flex1 flex column align-items-center">
        <picker-view indicator-style="height: 50px;" mode="selector" value="{{ [hourValue] }}" class="selector__picker" bindchange="hourChange">
          <picker-view-column>
            <view wx:for="{{ hourArr }}" wx:key="index" style="line-height: 50px" class="text-center">{{ item }}</view>
          </picker-view-column>
        </picker-view>
      </view>
      <!-- 分钟 -->
      <view class="flex1 flex column align-items-center">
        <picker-view indicator-style="height: 50px;" mode="selector" value="{{ [minValue] }}" class="selector__picker" bindchange="minChange">
          <picker-view-column>
            <view wx:for="{{ minArr }}" wx:key="index" style="line-height: 50px" class="text-center">{{ item }}</view>
          </picker-view-column>
        </picker-view>
      </view>
    </view>

    <view class="ft flex align-items-center justify-content-space-between">
      <button type="default" style="width:45%;height: 40px;" class="weui-btn" bindtap="bindclose">取消</button>
      <button type="primary" style="width:45%;height: 40px;margin-top:0" class="weui-btn" bindtap="handleSubmit">确定</button>
    </view>
  </view>
</mp-half-screen-dialog>

js代码

const utils = require('../../utils/util')

Component({
  options: {
    addGlobalClass: true
  },

  properties: {
    show: {
      type: Boolean,
      value: false,
      observer: '_showChange'
    },
    type: {
      type: String,
      value: 'center' // 类型:'left' -- 现在往前   'center' -- 往前&往后   'right' -- 现在往后
    },
    year: {
      type: Number,
      value: 1 // '时间区间{year}年' month不为undefined时该项失效
    },
    month: {
      type: [Number, String],
      value: 'undefined' // 'month' 不为undefined时  year失效
    }
  },

  data: {
    dateIndex: null,
    hourValue: '',
    minValue: '',
    dateArr: [],
    hourArr: [],
    minArr: [],

    activeTime: null // 抛出的时间戳
  },

  methods: {
    _showChange(e) {
      if (e) {
        this.handleDateData()
        this.initData()
      }
    },

    handleSubmit() {
      this.bindclose()
      this.triggerEvent('change', { value: this.data.activeTime })
    },

    initData() {
      const now = +new Date()
      const index = this.data.dateArr.map(v => v.name).indexOf(utils.formatTime(now, '{m}月{d}日周{a}'))
      let tmp = this.data.dateArr
      tmp[index].name = '今天'

      this.setData({
        dateIndex: index,
        hourValue: utils.formatTime(now, '{h}'),
        minValue: utils.formatTime(now, '{i}'),
        dateArr: tmp,
        activeTime: now
      })
    },

    handleDateData() {
      const nowYear = new Date().getFullYear()
      let mins = []
      let hours = []
      let dates = []

      // 获取小时、分钟数组
      for (let i = 0; i < 60; i++) {
        mins.push(i.toString().length < 2 ? '0' + i : i.toString())
      }
      for (let j = 0; j < 24; j++) {
        hours.push(j.toString().length < 2 ? '0' + j : j.toString())
      }

      dates = this.getDays(nowYear)

      this.setData({
        hourArr: hours,
        minArr: mins,
        dateArr: dates
      })
    },

    getDays(year) {
      let pre_days = []
      let now_days = []
      let aft_days = []

      if (this.data.month == 'undefined') {
        /** 按年处理 */
        // 判断类型
        if (this.data.type == 'left') {
          for (let a = this.data.year; a >= 1; a--) {
            pre_days.push(...this.getDaysByYear(year - a, true))
          }
        } else if (this.data.type == 'right') {
          for (let b = 1; b <= this.data.year; b++) {
            aft_days.push(...this.getDaysByYear(year + b, true))
          }
        } else {
          for (let a = this.data.year; a >= 1; a--) {
            pre_days.push(...this.getDaysByYear(year - a, true))
          }
          for (let b = 1; b <= this.data.year; b++) {
            aft_days.push(...this.getDaysByYear(year + b, true))
          }
        }
        now_days = this.getDaysByYear(year)
      } else {
        /** 按月处理 */
        now_days = this.getDaysByMonth(year, this.data.type)
      }

      return pre_days.concat(now_days.concat(aft_days))
    },

    getDaysByYear(year, isIncludeYear) {
      let days = []
      for (let k = 1; k < 13; k++) {
        let each_days = new Date(year, k, 0).getDate()
        for (let _k = 1; _k <= each_days; _k++) {
          let time = +new Date(`${year}-${k}-${_k}`)
          if (isIncludeYear) {
            days.push({ name: utils.formatTime(time, '{y}年{m}月{d}日周{a}'), value: time })
          } else {
            days.push({ name: utils.formatTime(time, '{m}月{d}日周{a}'), value: time })
          }
        }
      }
      return days
    },

    getDaysByMonth(year, type) {
      let days = []
      let nowMonth = new Date().getMonth() + 1

      // 当月份传负的或0时当成本月
      if (this.data.month > 0) {
        let months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
        let pre_mons = []
        let aft_mons = []

        // 生成往前、往后的月份数组
        for (let k = 1; k <= this.data.month; k++) {
          let tmp_pre = months.indexOf(nowMonth) - k
          let tmp_aft = months.indexOf(nowMonth) + k
          pre_mons.unshift(months[tmp_pre < 0 ? 12 + tmp_pre : tmp_pre])
          aft_mons.push(months[tmp_aft > 12 ? tmp_aft - 12 : tmp_aft])
        }
        if (type != 'right') {
          // 往前的月份的日期
          pre_mons.forEach(v => {
            // 跨年
            let month_days = 0
            if (v > nowMonth) {
              month_days = new Date(year - 1, v, 0).getDate()
              for (let k = 1; k <= month_days; k++) {
                let time = +new Date(`${year - 1}-${v}-${k}`)
                days.push({ name: utils.formatTime(time, '{y}年{m}月{d}日周{a}'), value: time })
              }
            } else {
              month_days = new Date(year, v, 0).getDate()
              for (let k = 1; k <= month_days; k++) {
                let time = +new Date(`${year}-${v}-${k}`)
                days.push({ name: utils.formatTime(time, '{m}月{d}日周{a}'), value: time })
              }
            }
          })
        }

        // 本月的日期
        let month_days = new Date(year, nowMonth, 0).getDate()
        for (let k = 1; k <= month_days; k++) {
          let time = +new Date(`${year}-${nowMonth}-${k}`)
          days.push({ name: utils.formatTime(time, '{m}月{d}日周{a}'), value: time })
        }

        if (type != 'left') {
          // 往后的月份的日期
          aft_mons.forEach(_v => {
            // 跨年
            let month_days = 0
            if (_v < nowMonth) {
              month_days = new Date(year + 1, _v, 0).getDate()
              for (let k = 1; k <= month_days; k++) {
                let time = +new Date(`${year + 1}-${_v}-${k}`)
                days.push({ name: utils.formatTime(time, '{y}年{m}月{d}日周{a}'), value: time })
              }
            } else {
              month_days = new Date(year, _v, 0).getDate()
              for (let k = 1; k <= month_days; k++) {
                let time = +new Date(`${year}-${_v}-${k}`)
                days.push({ name: utils.formatTime(time, '{m}月{d}日周{a}'), value: time })
              }
            }
          })
        }
      } else {
        let month_days = new Date(year, nowMonth, 0).getDate()
        for (let k = 1; k <= month_days; k++) {
          let time = +new Date(`${year}-${nowMonth}-${k}`)
          days.push({ name: utils.formatTime(time, '{m}月{d}日周{a}'), value: time })
        }
      }

      return days
    },

    dateChange(e) {
      const day = this.data.dateArr[e.detail.value[0]]
      let time = day.value + (Number(this.data.hourValue) * 3600 + Number(this.data.minValue) * 60) * 1000
      this.setData({
        dateIndex: e.detail.value[0],
        activeTime: time
      })
    },

    hourChange(e) {
      const hour = Number(this.data.hourArr[e.detail.value[0]])
      let time = this.data.dateArr[this.data.dateIndex].value + (hour * 3600 + Number(this.data.minValue) * 60) * 1000
      this.setData({
        hourValue: this.data.hourArr[e.detail.value[0]],
        activeTime: time
      })
    },

    minChange(e) {
      const min = Number(this.data.minArr[e.detail.value[0]])
      let time = this.data.dateArr[this.data.dateIndex].value + (Number(this.data.hourValue) * 3600 + min * 60) * 1000
      this.setData({
        minValue: this.data.minArr[e.detail.value[0]],
        activeTime: time
      })
    },

    bindclose() {
      this.setData({
        show: false
      })
    },

    preventTouchMove() {
      // 阻止半屏状态下 页面滑动
    }
  }
})

wxss代码

.selector__picker {
  width: 100%;
  height: 80%;
  margin-top: 20px;
  font-size: 24px;
}

上述代码中,js中引用的 utils 功能函数如下:

/**
 * 日期格式化
 */
export function formatTime(time, cFormat) {
  if (arguments.length === 0) {
    return ''
  }
  const format = cFormat || '{y}-{m}-{d}'
  let date
  if (time === undefined || time === 0 || time === '') {
    return ''
  } else if (typeof time === 'object') {
    date = time
  } else {
    if (('' + time).length === 10) time = parseInt(time) * 1000
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value]
    }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}

另外wxml中使用的一些wxss公共样式就不提供了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 微信小程序实现列表条件筛选

    本文实例为大家分享了微信小程序实现列表条件筛选的具体代码,供大家参考,具体内容如下 最近一个旅游项目,关于筛选框的代码 wxml文件 <view class='chooseList'>       <view class="nav">     <view class="nav-son {{shownavindex == 1? 'active' : ''}}" bindtap="listqy" data-nav=&qu

  • 微信小程序实现下拉筛选功能

    最近开发应项目需求实现一个类似与贝壳找房里面的下拉筛选功能,在这里分享给有同样需求的大家,互相学习学习 这是主要功能实现,我把它封装成了组件,在对应的地方使用,就可以实现贝壳找房相同的效果 好了,废话不多说,直接上代码吧 wxml: <!--筛选栏--> <view class="cxj-contents">   <view class="cxj-menu">     <view class="flex-view{

  • 微信小程序实现日期时间筛选器

    开发微信小程序过程中,有个需求需要用到日期时间筛选器,查看微信官方文档后,发现官方文档的picker筛选器只能单独支持日期或者是时间,所以为了实现需求自己参考企业微信封装了个日期时间筛选器组件. 原理 筛选器的实现,我参考的是小程序官方方式,通过半屏弹窗(mp-half-screen-dialog)结合picker_view进行日期.时间的选择,最终在选择时间后,通过事件触发返回一个change事件,其中参数值为毫秒级时间戳. 实现 1.弹窗的显隐: 在组件的 properties 中传入一个

  • 微信小程序wxs日期时间处理的实现示例

    目录 1.时间戳转日期 2.UTC转北京时间 WXS(WeiXin Script)是小程序的一套脚本语言,wxs 与 javascript 是不同的语言,有自己的语法,并不和 javascript 一致.其中包括了很多日常使用的javascript函数,在wxs中都是不能同样使用的.最近在做一个列表的时候,涉及到时间格式化操作.就遇到了这个问题,以前写好了的格式化工具函数直接拷贝到小程序项目的wxs文件中,函数不能正常执行.其中包括了下面的几个错误 正则表达式在字符串的replace函数中的使用

  • 微信小程序 选择器(时间,日期,地区)实例详解

    微信小程序 选择器(时间,日期,地区) 微信小程序 开发由于本人最近学习微信小程序的开发,根据自己的实践结果整理了下结果,对日期选择器,时间选择器,地区选择器做的实例,有不对的地方,希望大家指正. 用微信封装好的控件感觉很好,为我们开发人员省去了很多麻烦.弊端就是不能做大量的自定义.今天试用了选择器. 上gif: 上代码: 1.index.js //index.js //获取应用实例 var app = getApp() Page({ data: { date: '2016-11-08', ti

  • 微信小程序 滚动选择器(时间日期)详解及实例代码

    微信小程序  滚动选择器(时间日期)详解 微信小程序自己封装了很多控件,用起来确实很方便,如果这是Android里面,还需要自己去定义,不废话,效果图: 一起来看看怎么实现的呢?看完你应该就该说,尼玛,这就行啦-. 这个效果呢,要用到picker组件,动画从底部弹起的滚动选择器,现支持三种选择器,通过mode来区分,分别是普通选择器,时间选择器,日期选择器,默认是普通选择器. 看下相应的属性: 具体的来看看代码,布局: <view class="section" > <

  • 详解微信小程序获取当前时间及日期的方法

    获取当前时间 首先,在要获取时间的.js文件中加载util.js文件 然后在onload方法中,调用util.js中的formatTime方法获取当前时间 //获取当前时间 // 调用函数时,传入new Date()参数,返回值是日期和时间 var TIME = util.formatTime(new Date()); this.setData({ time: TIME, }); 这样就获取到了当前时间,但是我们发现在util.js中并没有获取当前日期的方法. 没事,别慌! 这个时候我们去看下u

  • 微信小程序  滚动选择器(时间日期)详解及实例代码

    微信小程序  滚动选择器(时间日期)详解 微信小程序自己封装了很多控件,用起来确实很方便,如果这是Android里面,还需要自己去定义,不废话,效果图: 一起来看看怎么实现的呢?看完你应该就该说,尼玛,这就行啦-. 这个效果呢,要用到picker组件,动画从底部弹起的滚动选择器,现支持三种选择器,通过mode来区分,分别是普通选择器,时间选择器,日期选择器,默认是普通选择器. 看下相应的属性: 具体的来看看代码,布局: <view class="section" > <

  • 微信小程序的日期选择器的实例详解

    微信小程序的日期选择器的实例详解 前言: 关于微信小程序中的日期选择器大家用过都会发现有个很大的问题,就是在2月的时候会有31天,没有进行对闰年的判断等各种情况.看了官方文档提供的源码后进行了一些修改,测试修复了上面所说的bug! 下面源码: <!---js---> const date = new Date();//获取系统日期 const years = [] const months = [] const days = [] const bigMonth = [1,3,5,7,8,10,

  • 微信小程序实现日期格式化和倒计时

    本文实例为大家分享了微信小程序实现日期格式化和倒计时的具体代码,供大家参考,具体内容如下 首先看看日期怎么格式化 第一种: Date.prototype.Format = function (fmt) { //author: meizz var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "h+": this.getHours(), //小时 "m+&q

  • 微信小程序获取当前时间及星期几的实例代码

    效果图如下所示 实例代码如下: util.js function formatTime(date) { var year = date.getFullYear() var month = date.getMonth() + 1 var day = date.getDate() var hour = date.getHours() var minute = date.getMinutes() var second = date.getSeconds() return [year, month, d

  • 微信小程序实现日期范围选择

    本文实例为大家分享了微信小程序实现日期范围选择的具体代码,供大家参考,具体内容如下 样式如下: 分别点击开始日期和结束日期选择时间(底部弹框): date.wxml:  <view class="range-style mar-top">                 <view class="picker-title">日期范围:</view>                 <!-- 时间段 -->      

随机推荐