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 小时前
案例-表白墙简单实现
前端·javascript·css
安冬的码畜日常1 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
小御姐@stella1 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing1 小时前
【React】增量传输与渲染
前端·javascript·面试
GISer_Jing1 小时前
WebGL在低配置电脑的应用
javascript
万叶学编程5 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js
天涯学馆7 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF7 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi7 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器