微信小程序?qū)崿F(xiàn)日期時間篩選器
開發(fā)微信小程序過程中,有個需求需要用到日期時間篩選器,查看微信官方文檔后,發(fā)現(xiàn)官方文檔的picker篩選器只能單獨支持日期或者是時間,所以為了實現(xiàn)需求自己參考企業(yè)微信封裝了個日期時間篩選器組件。
原理
篩選器的實現(xiàn),我參考的是小程序官方方式,通過半屏彈窗(mp-half-screen-dialog)結(jié)合picker_view進行日期、時間的選擇,最終在選擇時間后,通過事件觸發(fā)返回一個change事件,其中參數(shù)值為毫秒級時間戳。
實現(xiàn)
1.彈窗的顯隱:
在組件的 properties 中傳入一個 show 字段,用于控制彈窗的顯隱;默認值為 false。
2.篩選器類型:
為了更好的兼容性,提供一個 type 字段,用于控制篩選器的所支持 可選擇日期 的走向(往前、往后、前后都支持);默認值為 center(前后都支持)。
3.時間區(qū)間(年):
year 字段用于控制篩選器的年維度時間區(qū)間范圍;默認值為 1。
4.時間區(qū)間(月):
month 字段用于控制篩選器的月維度時間區(qū)間范圍。默認值為 ‘undefined’****(聲明’month’ 不為undefined時 year失效)。
具體思路:整體思路是監(jiān)聽彈窗的顯隱(show),當彈窗顯示時,獲取對應配置項(類型、年、月)計算對應篩選器的范圍,并初始化默認日期時間為當前年月日時分。
以下是效果圖以及具體代碼實現(xiàn):
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' -- 現(xiàn)在往前 ? 'center' -- 往前&往后 ? 'right' -- 現(xiàn)在往后 ? ? }, ? ? year: { ? ? ? type: Number, ? ? ? value: 1 // '時間區(qū)間{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}月vvxyksv9kd日周{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 = [] ? ? ? // 獲取小時、分鐘數(shù)組 ? ? ? 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}月vvxyksv9kd日周{a}'), value: time }) ? ? ? ? ? } else { ? ? ? ? ? ? days.push({ name: utils.formatTime(time, '{m}月vvxyksv9kd日周{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 = [] ? ? ? ? // 生成往前、往后的月份數(shù)組 ? ? ? ? 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}月vvxyksv9kd日周{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}月vvxyksv9kd日周{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}月vvxyksv9kd日周{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}月vvxyksv9kd日周{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}月vvxyksv9kd日周{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}月vvxyksv9kd日周{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() { ? ? ? // 阻止半屏狀態(tài)下 頁面滑動 ? ? } ? } })
wxss代碼
.selector__picker { ? width: 100%; ? height: 80%; ? margin-top: 20px; ? font-size: 24px; }
上述代碼中,js中引用的 utils 功能函數(shù)如下:
/** ?* 日期格式化 ?*/ export function formatTime(time, cFormat) { ? if (arguments.length === 0) { ? ? return '' ? } ? const format = cFormat || '{y}-{m}-vvxyksv9kd' ? 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公共樣式就不提供了。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
微信小程序調(diào)用wx.getImageInfo遇到的坑解決
這篇文章主要介紹了微信小程序調(diào)用wx.getImageInfo遇到的坑解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05JavaScript實現(xiàn)點擊單選按鈕改變輸入框中文本域內(nèi)容的方法
這篇文章主要介紹了JavaScript實現(xiàn)點擊單選按鈕改變輸入框中文本域內(nèi)容的方法,涉及javascript單選按鈕控制頁面元素樣式的相關技巧,非常簡單實用,需要的朋友可以參考下2015-08-08TypeScript中的interface與type實戰(zhàn)
這篇文章主要介紹了TypeScript中的interface與type詳解,它們都是用來定義類型的強大工具,在實際開發(fā)中,你可以根據(jù)具體情況選擇使用 interface 或 type,或者甚至將它們結(jié)合起來使用,需要的朋友可以參考下2023-06-06HBuilderX開發(fā)一個簡單的微信小程序的實現(xiàn)步驟
本文主要介紹了HBuilderX開發(fā)一個簡單的微信小程序的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02