vue3 setup+Taro3 调用原生小程序自定义年月日时分多列选择器,NutUI改造
NutUI 有日期时间选择器,但是滑动效果太差,卡顿明显。换成 原生小程序 很顺畅
上代码:
javascript
<template>
<view>
<picker
mode="multiSelector"
@change="confirmPicker"
@columnChange="scrollColumnChange"
:value="columnVal"
:range="multiArray"
>
<nut-cell
title="选择时间"
:desc="showVal"
@click="copyColumnVal = columnVal"
></nut-cell>
<!-- <view @click="copyColumnVal = columnVal">
当前选择:{{ showVal }}
</view> -->
</picker>
</view>
</template>
<script setup>
import { ref, onMounted, watch } from "vue";
const multiArray = ref(undefined); // 列可选列表
const columnVal = ref(undefined); // 列当前选中值
const copyColumnVal = ref(undefined); // 记录滚动中数据
const showVal = ref(undefined); // 显示:后年月日时分
// 个位数时 补0
const add0 = (num) => String(num > 9 ? num : "0" + num);
// 判断平年闰年
const resYearType = (year) =>
(year % 4 == 0) & (year % 100 != 0) || year % 400 == 0;
// 获取当前时间
const getNowT = (timeInfo) => {
// timeInfo 为 年月日字符串 或者 时间戳
var nowT = new Date(timeInfo);
return {
year: nowT.getFullYear(),
month: nowT.getMonth() + 1,
day: nowT.getDate(),
hour: nowT.getHours(),
minute: nowT.getMinutes(),
second: nowT.getSeconds(),
};
};
// 设置当前时间 - columnVal:每列索引数组集合
function setNowTime(timeStr) {
const timeObj = getNowT(timeStr); // timeObj 为: { year, month, day... }
const { year, month, day, hour, minute } = timeObj;
// 获取滚动列表数据
const [
years,
months,
days,
hours,
minutes,
] = multiArray.value;
const yearsIdx = years.findIndex((item) => item == year);
const monthsIdx = months.findIndex((item) => item == month);
const daysIdx = days.findIndex((item) => item == day);
const hoursIdx = hours.findIndex((item) => item == hour);
const minutesIdx = minutes.findIndex((item) => item == minute);
columnVal.value = [yearsIdx, monthsIdx, daysIdx, hoursIdx, minutesIdx];
showVal.value = `${year}/${add0(month)}/${add0(day)} ${add0(hour)}:${add0(
minute
)}`;
// 根据当前时间,初始化可选择日期时间
setDaysList(columnVal.value)
}
// 初始化时间
function initColumn(daysNum = 31) {
// 年
const yearStart = 2000; // 年 - 开始时间
const yearLength = 100; // 年 - 列表长度
const years = Array.from({ length: yearLength }).map((i, idx) =>
add0((idx += yearStart))
);
// 月
const months = Array.from({ length: 12 }).map((i, idx) => add0((idx += 1)));
// 日
const days = Array.from({ length: daysNum }).map((i, idx) =>
add0((idx += 1))
);
// 时
const hours = Array.from({ length: 24 }).map((i, idx) => add0((idx += 0)));
// 分
const minutes = Array.from({ length: 60 }).map((i, idx) => add0((idx += 0)));
multiArray.value = [
years,
months,
days,
hours,
minutes,
];
}
// 滚动设置可选天数 28 - 29 - 30 - 31
function setDays(daysNum = 31) {
multiArray.value[2] = Array.from({ length: daysNum }).map((i, idx) =>
add0((idx += 1))
);
// 深拷贝下,否则不动态修改列
multiArray.value = JSON.parse(JSON.stringify(multiArray.value));
}
// 修改每月的天数
function setDaysList(columnArr) {
const [yearsIdx, monthsIdx] = columnArr;
const [years] = multiArray.value;
// 当选择2月
if (monthsIdx == 1) {
// 如果闰年
if (resYearType(years[yearsIdx])) {
setDays(29);
} else {
setDays(28);
}
} else if ([1, 3, 5, 7, 8, 10, 12].includes(monthsIdx + 1)) {
// 当选择1, 3, 5, 7, 8, 10, 12月
setDays(31);
} else {
setDays(30);
}
}
// 确认选中结果
function confirmPicker(e) {
columnVal.value = e.detail.value;
const [yearsIdx, monthsIdx, daysIdx, hoursIdx, minutesIdx] = e.detail.value;
const [years, months, days, hours, minutes] = multiArray.value;
showVal.value = `${years[yearsIdx]}/${months[monthsIdx]}/${days[daysIdx]} ${hours[hoursIdx]}:${minutes[minutesIdx]}`;
}
// 滚动事件(未点击确定)
function scrollColumnChange(e) {
const { column, value } = e.detail;
copyColumnVal.value[column] = value;
setDaysList(copyColumnVal.value);
console.log("修改的列为", column, ",值为", value);
}
// 初始化
onMounted(() => {
initColumn();
// 回显时间
setNowTime(new Date().getTime());
});
// 监听传递日期
const props = defineProps({
propsTime: {
type: String,
default: ''
}
})
watch(props.propsTime, (newValue, oldValue) => {
console.log('值发生了变更', newValue, oldValue);
// 回显时间
setNowTime(newValue);
});
</script>
若需要自定义年开始时间,见 initColumn 方法
如作为组件,通过父级传递,可使用: