vue3 setup+Taro3 调用原生小程序自定义年月日时分多列选择器,NutUI改造

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 方法

如作为组件,通过父级传递,可使用:

相关推荐
百万蹄蹄向前冲1 小时前
2024不一样的VUE3期末考查
前端·javascript·程序员
alikami1 小时前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
V+zmm101342 小时前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
还这么多错误?!2 小时前
uniapp微信小程序,使用fastadmin完成一个一键获取微信手机号的功能
微信小程序·小程序·uni-app
wakangda2 小时前
React Native 集成原生Android功能
javascript·react native·react.js
_院长大人_2 小时前
微信小程序用户信息解密 AES/CBC/NoPadding 解密失败问题
微信小程序·小程序
吃杠碰小鸡2 小时前
lodash常用函数
前端·javascript
emoji1111112 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
一个处女座的程序猿O(∩_∩)O2 小时前
vue3 如何使用 mounted
前端·javascript·vue.js
User_undefined3 小时前
uniapp Native.js原生arr插件服务发送广播到uniapp页面中
android·javascript·uni-app