uviewplus中的时间单选框up-datetime-picker的在uni-app+vue3的使用方法
uviewplus中的时间单选框up-datetime-picker的使用方法
前言
在实际开发中,我们经常需要使用时间选择器来让用户选择特定的时间。本文将详细介绍uviewplus中up-datetime-picker组件的使用方法,特别是在处理年月选择时的一些关键实现,因为官方有很多相关的功能和方法在文档中没有说明清楚,所以我做了许多调试,终于完成了。
基础使用
1. 组件引入
<template>
<view class="datetime-picker-container">
<view class="picker-wrapper" @click="openPicker">
<text class="picker-label">选择日期:</text>
<view class="picker-input">{{getTimeYearAndMouth(yearMonth)}}</view>
</view>
<up-datetime-picker
v-if="selectTimeStampList.length > 0"
v-model="yearMonth"
mode="year-month"
:show="timeSelectShow"
:formatter="formatter"
:filter="filterTime"
format="YYYY-MM"
@cancel="cancelPicker"
@confirm="confirmPicker"
/>
</view>
</template>
2. 基础数据定义
// 当前选中的时间戳
const yearMonth = ref(Date.now())
// 控制选择器显示/隐藏
const timeSelectShow = ref(false)
// 可选时间戳列表
const selectTimeStampList = reactive<number[]>([])
// 年份去重数组 - 关键数据结构
const fitterTheSameYears = reactive<number[]>([])
核心实现
1. 时间映射表
// 创建一个 Map 来存储有效的年月组合
const validDateMap = computed(() => {
const dateMap = new Map()
if (!selectTimeStampList?.length) {
return dateMap
}
selectTimeStampList.forEach(timestamp => {
const date = new Date(timestamp)
const year = date.getFullYear()
const month = date.getMonth() + 1
if (!dateMap.has(year)) {
dateMap.set(year, new Set())
}
dateMap.get(year).add(month)
})
return dateMap
})
2. 格式化器实现
重点,如果没有按照规范过滤的话会产生一系列问题。
const formatter = (type: string, value: number) => {
// 处理特殊情况,当切换年月份的时候最后会传进两个被选择的参数,所以需要处理 [2024, 01] 的情况
if (value.toString().length < 5){
if (type === 'year') {
return `${value}年`
}
if (type === 'month') {
fitterTheSameYears.length = 0 // 重要: 清空年份数组
// 判断月份字符串是否以 0 开头,如果是的话,则取第二个字符,否则取整个字符串 ,因为这样的格式才能正常选中
return value.startsWith('0') ? `${value[1]}月` : `${value}月`
}
}
// 基础类型检查
if (!value || typeof value !== 'number') {
return ''
}
const date = new Date(value)
const year = date.getFullYear()
const month = date.getMonth() + 1
if (type === 'year') {
if (!validDateMap.value.size) {
return `${year}年`
}
// 检查是否是有效年份并去重
if (validDateMap.value.has(year) && !fitterTheSameYears.includes(year)) {
fitterTheSameYears.push(year)
return `${year}年`
}
return null
}
if (type === 'month') {
if (!validDateMap.value.size) {
return `${month}月`
}
// 检查当前年份下的月份是否有效
const currentYear = new Date(yearMonth.value || Date.now()).getFullYear()
const validMonths = validDateMap.value.get(currentYear)
if (validMonths && validMonths.has(month)) {
return `${month}月`
}
return null
}
return value.toString()
}
3. 事件处理方法
// 打开选择器
const openPicker = () => {
timeSelectShow.value = true
}
// 格式化显示时间
const getTimeYearAndMouth = (timestamp: number) => {
const date = new Date(timestamp)
return `${date.getFullYear()}年${date.getMonth() + 1}月`
}
// 确认选择
const confirmPicker = (data) => {
yearMonth.value = data.value
timeSelectShow.value = false
// 这里可以添加选择后的业务处理逻辑
}
// 取消选择
const cancelPicker = () => {
timeSelectShow.value = false
}
重要说明
1. fitterTheSameYears的作用
- 用于存储已处理的年份,防止重复显示
- 在切换到月份选择时需要清空
- 确保年份选项的唯一性
2. formatter函数的关键点
- 需要处理特殊的数值情况
- 年份和月份的显示格式化
- 配合fitterTheSameYears进行年份去重
- 根据validDateMap过滤无效选项
3. 时间选择的注意事项
- 切换年份时会影响可选月份
- 确保时间戳格式统一
- 处理无数据的边界情况
常见问题
1. 无法切换年份或月份
可能的原因:
- formatter返回值不正确
- fitterTheSameYears未正确维护
- validDateMap数据异常
解决方案:
- 检查formatter的返回值
- 确保在适当时机清空fitterTheSameYears
- 验证时间戳列表的正确性
2. 显示异常
可能的原因:
- 时间戳格式不统一
- 特殊数值处理不当
- v-if条件判断有误
解决方案:
- 统一使用毫秒级时间戳
- 完善特殊情况的处理
- 检查组件显示条件
最佳实践
- 数据初始化
- 确保selectTimeStampList在使用前已正确初始化
- 使用reactive而不是ref定义数组
- 注意时间戳格式的统一性
- 性能优化
- 使用computed缓存validDateMap
- 避免在formatter中进行复杂计算
- 合理使用v-if控制组件渲染
- 用户体验
- 提供清晰的时间选择提示
- 处理好加载状态
- 确保选择器操作流畅