微信小程序实现日期时间筛选器
作者:就是有点怕怕 发布时间:2023-08-29 00:51:37
开发微信小程序过程中,有个需求需要用到日期时间筛选器,查看微信官方文档后,发现官方文档的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公共样式就不提供了。
来源:https://blog.csdn.net/weixin_42371354/article/details/122500184
猜你喜欢
- 学习WEB标准的朋友一般都是从学习CSS开始,为什么呢?因为CSS是一种很有意思的语言,它能让我们的网页千变万化。也许我们一开始的接触只是因
- 这篇论坛文章详细介绍了完全卸载MySQL数据库5.0的具体方法,更多内容请参考下文:数据库突然出了问题,没办法只能重装,因为事先并不知道My
- 最近开始在项目中使用Quickwork For Asp,虽然该框架是自己独立完成的,不过功能没做过详细的总结,所以很多参数总是会弄错,毕竟鱼
- 阅读上一篇:FrontPage XP设计教程2——网页的编辑 制作一个漂亮的网页,离不开网页整体布局的设计,网页布局设计的合理与否,直接影响
- 网上广泛流传的取 object 的绝对位置的做法是:var getAbsPos = function(pTar
- 不得不承认,傲游在用户体验方面是做得比较好的,所以它的用户群非常大。也正因为如此,它的某些不好的特性也造成了开发人员不可忽略的浏览器兼容问题
- jQuery的选择器可谓异常强大,没有什么DOM里的任何数据能逃出它的掌心,这点是我非常喜欢的,以前获取NODE要用getElementBy
- 等了好久的小程序,终于在近日曝光了。现在就带大家来尝尝鲜。以下是一张随便看看的图。一、构建微信小程序的步骤下载开发工具考虑到微信0.9.09
- 流动网页设计有很多好处,但也只有在正确使用的时候。合适的技巧会使页面在大屏幕、小屏幕抑、PDA小屏幕上都能得到良好的呈现。但是,糟糕的代码结
- innewDropList = [9,10,11,12,22,50,51,60,61]newDB = newDB[newDB['gr
- 不久之前,笔者一个在企业中从事网管工作的朋友向我求助关于SQL Server服务器内存升级后遇到的问题。原来,他们企业准备上一个企业邮箱系统
- 给每一个onClick再附加一个事件 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HT
- 数据库并行访问,也就是两个或两以上用户同时访问同一数据,这也是数据库引擎如何设计和实现适度反应所面临的最大问题。设计优良、性能卓越的数据库引
- 使用access数据库时可能用到的数据转换:类型转换涵数:函数 返回类型 expression 参数范围CBool Boolean 任何有效
- 用户体验已经是一个老生常谈的话题了。我非常赞同某位达人所说的,用户体验设计应该贯穿于产品从萌芽到出生的整个过程,产品原型、视觉设计、前端开发
- 本文实例为大家分享了React实现表格选取的具体代码,供大家参考,具体内容如下在工作中,遇到一个需求,在表格中实现类似于Excel选中一片区
- python学生成绩管理系统创建,供大家参考,具体内容如下要求编写学生类,班级类,并在电脑运行生成表单,输入一个数字,得到对应的结果。输出样
- 使用py时可能需要连续运行多条shell 命令1.# coding: UTF-8import sysreload(sys)sys.setde
- 也许你听说过Hibernate的大名,但可能一直不了解它,也许你一直渴望使用它进行开发,那么本文正是你所需要的!在本文中,我向大家重点介绍H
- 前言在工作中使用的是oracle数据库,平时想在家测试一些sql是否可以跑的过,可惜自己电脑并没有安装oracle数据库,甚至完全不想安装到