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

简单说一下功能点

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

在实现该功能还是有一些小的注意点的,最主要的就是-->日期选择需要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>

结束语

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

相关推荐
lpfasd1236 小时前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
Data analyse4569 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai9 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
环境栈笔记9 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
赵大仁10 小时前
官网性能优化实战:LCP 3.2s → 2.1s、CLS 0.107 → 0,以及被我推翻的 6 个判断
前端·性能优化·cls·lcp·core web vitals
xiancai_xianyu10 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
小羊没烦恼!10 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
史瓦辛格10 小时前
给 DeepSeek Harness 写费用插件:把「这次会话花了多少钱」算准
前端·deepseek
星光不问赶路人10 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js
鸥梨菌Honevid10 小时前
UVM 中 REQ 和 RSP 类型详解:从通信模型到 item_done 与 put_response
java·前端·servlet