手搓微信小程序生日滑动选择😉

简单说一下功能点

微信小程序设置用户的生日,直接使用日历有些不太友好,所以选择手搓一个类似某音和某红书差不多的样式。

在实现该功能还是有一些小的注意点的,最主要的就是-->日期选择需要3级联动,因为要获取当前年份有多少月份、以及当前年份的月份有多少天。总不能今天是2023年12月3号,但滑动选项里面有明天甚至以后的日期吧。

使用的是VantWeapp组件实现的滑动效果,当然,使用其他组件的一样,结尾附源代码。

功能样式图

日期选择默认的打开样式

在选择最新日期时候

除了选择天数不会去重新拉取日期外,当滑动触发年和月的改变,都需要去拉取最新的日期。若拉取的日期的天数或月份不够上一次选择的时候,默认会选择最后一个日期等等小细节吧。

主要代码功能

自己封装的一个时间工具

ts 复制代码
/**
 * 获取有多少年份[默认截至1949]
 * @param actYear 截至到多少年份
 * @returns 年份数组
 */
export const getYear = (actYear?: number): Array<number> => {
  actYear = actYear || 1949;
  const date = new Date();
  if (actYear >= date.getFullYear()) return [1949];
  let yearArr = [];
  for (let i = actYear; i <= date.getFullYear(); i++) yearArr.push(i);
  return yearArr;
};

/**
 * 获取当前年份有多少月份
 * @param year 年份
 * @returns 月份数组
 */
export const getMonthToYear = (year: number): Array<number> => {
  const date = new Date();
  const nowYear = date.getFullYear();
  if (year > nowYear) return [1];
  let monthArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
  if (year == nowYear) {
    monthArr = [];
    for (let i = 1; i <= date.getMonth() + 1; i++) monthArr.push(i);
  }
  return monthArr;
};

/**
 * 获取当前年的月份有多少天
 * @param year 年份
 * @param month 月份
 * @returns 天数数组
 */
export const getDayToMoYe = (year: number, month: number): Array<number> => {
  const date = new Date();
  const nowYear = date.getFullYear();
  const nowMonth = date.getMonth() + 1;
  if (year > nowYear) return [1];
  let monthArr = getMonthToYear(year);
  if (month > monthArr.length) return [1];
  let dayArr = [];
  if (year == nowYear && month == nowMonth) {
    for (let i = 1; i <= date.getDate(); i++) dayArr.push(i);
    return dayArr;
  }
  for (let i = 1; i <= new Date(year, month, 0).getDate(); i++) dayArr.push(i);
  return dayArr;
};

组件代码

特别说明:手动删掉了不重要的代码,请勿直接复制

html 复制代码
<template>
      <van-popup
        class="pd-10"
        :show="showDateChoose"
        round
        position="bottom"
        @close="showDateChoose = false">
        <view class="mt-10 flex-center-zy pd-zy-15">
          <view class="ft-color-hui" @click="showDateChoose = false">取消</view>
          <view>选择你的生日</view>
          <view class="ft-big-4 ft-color-red" @click="saveDate">保存</view>
        </view>
        <van-picker
          :columns="initDate"
          @change="onDateChange"
          :visible-item-count="3"
          :loading="dateLoding" />
      </van-popup>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive } from 'vue';
import FixVue from '@/common/pages/fix_vue/FixVue';
import { getYear, getMonthToYear, getDayToMoYe } from '@/utils/TimeUtil';

//展示日期选择框和日期加载
let showDateChoose = ref(false);
let dateLoding = ref(true);

//打开日期选择
const openDate = () => {
  dateLoding.value = true;
  showDateChoose.value = true;
  //测试数据,后需要修改为动态获取的用户生日,若用户生日没有则给默认值
  initDateMethod('2001-5-10');
  dateLoding.value = false;
};

//保存日期
let newDate = ref('');
const saveDate = () => {
  if (!newDate.value) return;
  //与原本日期进行对比若不同,调用修改生日的接口。。。
};

//选择新时间
const onDateChange = (e: any) => {
  const { picker, index } = e.detail;
  if (index == 2) return (newDate.value = picker.getValues());
  const upDate = picker.getIndexes();
  const year = initDate.value[0].values[upDate[0]];
  const month = initDate.value[1].values[upDate[1]];
  const day = initDate.value[2].values[upDate[2]];
  initDate.value = [];
  const result = initDateMethod(year + '-' + month + '-' + day);
  newDate.value = picker.getValues();
  setTimeout(() => {
    picker.setColumnIndex(0, result[0]);
    picker.setColumnIndex(1, result[1]);
    picker.setColumnIndex(2, result[2]);
  }, 10);
};

//初始化年份
let initDate = ref([]);
const initDateMethod = (date: string) => {
  let dateSplit = date.split('-');
  const year = getYear();
  const month = getMonthToYear(+dateSplit[0]);
  const day = getDayToMoYe(+dateSplit[0], +dateSplit[1]);
  let yearIndex = year.indexOf(+dateSplit[0]) == -1 ? year.length - 1 : year.indexOf(+dateSplit[0]);
  initDate.value.push({
    values: year,
    defaultIndex: yearIndex
  });
  let monthIndex =
    month.indexOf(+dateSplit[1]) == -1 ? month.length - 1 : month.indexOf(+dateSplit[1]);
  initDate.value.push({
    values: month,
    defaultIndex: monthIndex
  });
  let dayIndex = day.indexOf(+dateSplit[2]) == -1 ? day.length - 1 : day.indexOf(+dateSplit[2]);
  initDate.value.push({
    values: day,
    defaultIndex: dayIndex
  });
  return [yearIndex, monthIndex, dayIndex];
};
</script>

//主要的css样式,主要添加日期后面的一些提示字,如年、月、日
<style lang="less" scoped>
::v-deep.van-picker-column__item--selected {
  color: black;
}
::v-deep[data-index='0'] {
  .van-picker-column__item--selected::after {
    content: ' 年';
  }
}
::v-deep[data-index='1'] {
  .van-picker-column__item--selected::after {
    content: ' 月';
  }
}
::v-deep[data-index='2'] {
  .van-picker-column__item--selected::after {
    content: ' 日';
  }
}
::v-deep.van-picker {
  height: 150px !important;
  margin-top: 20px;
}
</style>

结束语

至此功能就完结了,接下来已编写完成仿某信的聊天样式,如自动根据输入框弹起高度修改聊天内容触底,以及动态调整输入框的高度和最大限制等等。若有需求的小伙伴,可以聊聊,我会分享个人的想法以及做法,若需求大会写一篇文章以及源码分享。

相关推荐
小小小小宇2 小时前
前端并发控制管理
前端
小小小小宇2 小时前
前端SSE笔记
前端
小小小小宇2 小时前
前端 WebSocket 笔记
前端
小小小小宇3 小时前
前端visibilitychange事件
前端
小小小小宇4 小时前
前端Loader笔记
前端
烛阴5 小时前
从0到1掌握盒子模型:精准控制网页布局的秘诀
前端·javascript·css
前端工作日常8 小时前
我理解的`npm pack` 和 `npm install <local-path>`
前端
李剑一8 小时前
说个多年老前端都不知道的标签正确玩法——q标签
前端
嘉小华8 小时前
大白话讲解 Android屏幕适配相关概念(dp、px 和 dpi)
前端
姑苏洛言8 小时前
在开发跑腿小程序集成地图时,遇到的坑,MapContext.includePoints(Object object)接口无效在组件中使用无效?
前端