vue3+ts+uniapp小程序端自定义日期选择器基于内置组件picker-view + 扩展组件 Popup 实现自定义日期选择及其他选择

news2025/1/18 6:59:16

vue3+ts 基于内置组件picker-view + 扩展组件 Popup 实现自定义日期选择及其他选择

vue3+ts+uniapp小程序端自定义日期选择器

  • 1.先上效果图
  • 2.代码展示
    • 2.1 组件
    • 2.2 公共方法处理日期
    • 2.3 使用组件
  • 3.注意事项
    • 3.1`refSelectDialog`
    • 3.1 `backgroundColor="#fff"`

自我记录

1.先上效果图

![在这里插入图片描述](https://img-blog.csdnimg.cn/48ecbb2775794a7cbec358e2c4017a3a.png
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
直接上代码

2.代码展示

2.1 组件

src\components\HbcyPopup.vue

<script setup lang="ts">
import { formatDate, parseDate } from '@/utils'
import { ref } from 'vue'

const props = defineProps<{
  popupTitle: string
  type: 'year' | 'month' | 'day'
  defaultDate: string
}>()
const emit = defineEmits<{
  (e: 'confirm-popup', params: string): void
  (e: 'close-popup'): void
}>()

// 选中的值
const selectDate = ref('')
// 创建选择区间 参考uni文档
const date = new Date()
// 年月日
const TYPEYY_MM_DD = props.type === 'year' || props.type === 'month' || props.type === 'day'
// 月日
const TYPEMM_DD = props.type === 'month' || props.type === 'day'
const TYPEYY = props.type === 'year'
const TYPEMM = props.type === 'month'
const TYPEDD = props.type === 'day'
const years = TYPEYY_MM_DD
  ? Array.from({ length: date.getFullYear() - 1989 }, (_, index) => 1990 + index)
  : []
const months = TYPEMM_DD ? Array.from({ length: 12 }, (_, index) => index + 1) : []
const days = TYPEDD ? Array.from({ length: 31 }, (_, index) => index + 1) : []
// 处理默认展示的时间
const defaultDate = parseDate(props.defaultDate, props.type)
// 确保默认时间
const year = ref<number>(defaultDate[0])
const month = ref<number | undefined>(defaultDate[1])
const day = ref<number | undefined>(defaultDate[2])
// 区分日期展示
let showValueList: any = []
// 展示日期的选中时间
if (TYPEDD) {
  showValueList = [
    years.indexOf(defaultDate[0]),
    months.indexOf(defaultDate[1]!),
    days.indexOf(defaultDate[2]!),
  ]
} else if (TYPEMM) {
  showValueList = [years.indexOf(defaultDate[0]), months.indexOf(defaultDate[1]!)]
} else if (TYPEYY) {
  showValueList = [years.indexOf(defaultDate[0])]
}
const valueList = ref<number[]>(showValueList)

// 切换日期
const bindChange: UniHelper.PickerViewOnChange = (e) => {
  const val = e.detail.value
  year.value = years[val[0]]
  month.value = months[val[1]]
  day.value = days[val[2]]
}
// 确定按钮
const onClickConfirmPopup = (): void => {
  selectDate.value = formatDate(year.value, month.value, day.value)
  emit('confirm-popup', selectDate.value)
  onClosePopup()
}
// 关闭弹出层
const onClosePopup = (): void => {
  emit('close-popup')
}
</script>

<template>
  <view class="selectBox">
    <view class="selectTitle">
      <text class="cancel" @click="onClosePopup">取消</text>
      <text class="title">{{ '选择' + popupTitle }}</text>
      <text class="cancel ok" @click="onClickConfirmPopup">确定</text>
    </view>
    <block v-if="TYPEYY_MM_DD">
      <picker-view
        :immediate-change="true"
        indicator-class="indicatorClass"
        :value="valueList"
        @change="bindChange"
        class="picker-view"
      >
        <picker-view-column>
          <view class="item" v-for="(item, index) in years" :key="index">{{ item }}</view>
        </picker-view-column>
        <picker-view-column v-if="TYPEMM_DD">
          <view class="item" v-for="(item, index) in months" :key="index">{{ item }}</view>
        </picker-view-column>
        <picker-view-column v-if="TYPEDD">
          <view class="item" v-for="(item, index) in days" :key="index">{{ item }}</view>
        </picker-view-column>
      </picker-view>
    </block>
    <!-- TODO -->
    <block v-else> <text>我是单列</text> </block>
  </view>
</template>

<style lang="scss" scoped>
::v-deep.indicatorClass {
  height: 100rpx;
}
.picker-view {
  width: 750rpx;
  height: 600rpx;
  margin-top: 20rpx;
}
.item {
  line-height: 100rpx;
  text-align: center;
}
.selectBox {
  width: 100%;
  height: 720rpx;
  background-color: #fff;
  border-radius: 20rpx 20rpx 0 0;
  .selectTitle {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 100rpx;
    font-size: 32rpx;
    .cancel {
      width: 160rpx;
      text-align: center;
      color: #ff976a;
    }
    .ok {
      color: #07c160;
    }
  }
}
</style>

2.2 公共方法处理日期

src\utils\index.ts

// 将 yyyy-mm-dd 的字符串 2023-08-24 => [2023,8,24] || [2023,8] || [2023]
export function parseDate(dateString: string, type: string): [number, number?, number?] {
  const date = dateString ? new Date(dateString) : new Date()
  const year = date.getFullYear()
  const month = type === 'day' || type === 'month' ? date.getMonth() + 1 : undefined
  const day = type === 'day' ? date.getDate() : undefined
  return [year, month, day]
}

// 将数字格式的年、月、日转换成格式为 yyyy-mm-dd 的字符串 || yyyy-mm || yyyy
export function formatDate(year: number, month?: number, day?: number): string {
  const formattedMonth = month !== undefined ? (month < 10 ? `0${month}` : `${month}`) : ''
  const formattedDay = day !== undefined ? (day < 10 ? `0${day}` : `${day}`) : ''
  return `${year}${formattedMonth ? `-${formattedMonth}` : ''}${
    formattedDay ? `-${formattedDay}` : ''
  }`
}

2.3 使用组件

src\pages\test\index.vue

<script setup lang="ts">
import type { Ref } from 'vue'
import { ref } from 'vue'

// 日期相关
const isShowPopop = ref(false)
// 弹出层实例
const refSelectDialog: Ref<UniHelper.UniPopup | null> = ref(null)
const dateTime = ref('')
// 打开日期弹窗
const onClcikPopup = () => {
  refSelectDialog.value!.open()
  isShowPopop.value = true
  console.log(refSelectDialog, 'refPopup')
}
// 关闭弹窗
const onClosePopup = () => {
  refSelectDialog.value!.close()
  isShowPopop.value = false
}
// 确定日期弹窗
const onConfirmPopup = (params: string) => {
  dateTime.value = params
  console.log(dateTime.value, 'dateTime.value')
}
</script>

<template>
  <view class="test-page">
    <!-- 展示信息 -->
    <view @tap="onClcikPopup" class="item-date">
      <text class="item-date-placeholder" v-show="!dateTime">请选择时间</text>
      <text class="item-date-txt" v-show="dateTime">{{ dateTime }}</text>
    </view>
    <!-- 使用组件 -->
    <uni-popup
      ref="refSelectDialog"
      type="bottom"
      class="selectDialogBox"
      :maskClick="false"
      :isMaskClick="false"
      backgroundColor="#fff"
      :close="onClosePopup"
    >
      <HbcyPopup
        v-if="isShowPopop"
        popupTitle="日期"
        type="day"
        :defaultDate="dateTime"
        @confirm-popup="onConfirmPopup"
        @close-popup="onClosePopup"
      />
    </uni-popup>
  </view>
</template>

<style lang="scss" scoped>
.test-page {
  .item-date {
    width: 300rpx;
    height: 60rpx;
    line-height: 60rpx;
    text-align: center;
    border: 1rpx solid #999;
    font-size: 28rpx;

    &-placeholder {
      color: #999;
    }

    &-txt {
      color: #333;
    }
  }
}
</style>

3.注意事项

3.1refSelectDialog

// 弹出层实例
const refSelectDialog: Ref<UniHelper.UniPopup | null> = ref(null)
  • ts类型有一些问题,找了好久不知道该给什么类型!!! 新手TS,有大佬的话请指出,感谢!

3.1 backgroundColor="#fff"

<uni-popup backgroundColor="#fff" /> 
  • 因为默认是开启适配的,需要加上背景色,否则就是透明的底部区域
  • 示例如下:
  • 在这里插入图片描述
  • 源码查看
  • 在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    整理不易,如有转载请备注原文地址!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/926290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Little Kernel代码学习笔记

目录 虚拟地址转换为物理地址内核启动Multiboot头部结构启动时的寄存器状态real_start段选择子初始化BSS段 页表转换设置CR4、CR3、EFER寄存器设置页表映射 初始化IDT&#xff0c;执行lk_main 虚拟地址转换为物理地址 // start.S#define PHYS_LOAD_ADDRESS (MEMBASE KERNEL_L…

Docker去除sudo权限

Docker去除sudo权限 使用docker命令时&#xff0c;每次都要sudo提权&#xff0c;否则就会报错提示无权限。 1.查看docker用户组及成员 sudo cat /etc/group | grep docker2.添加docker用户组 sudo groupadd docker3.添加用户到docker组 sudo gpasswd -a ${USER} docker4.增…

“超级AI助手:全新提升!中文NLP训练框架,快速上手,海量训练数据,ChatGLM-v2、中文Bloom、Dolly_v2_3b助您实现更智能的应用!”

“超级AI助手&#xff1a;全新提升&#xff01;中文NLP训练框架&#xff0c;快速上手&#xff0c;海量训练数据&#xff0c;ChatGLM-v2、中文Bloom、Dolly_v2_3b助您实现更智能的应用&#xff01;” 1.简介 目标&#xff1a;基于pytorch、transformers做中文领域的nlp开箱即用…

【android12-linux-5.1】【ST芯片】驱动移植后编译不通过

ST传感器芯片驱动移植后&#xff0c;编译报错timespec_to_ns未定义&#xff0c;这应该是内核版本的差异引起的。驱动的适配版本是4.19y&#xff0c;我实际使用的内核linux版本是5.1。 处理方法是使用timespec64_to_ns&#xff0c;如下图&#xff1a; 新代码如下&#xff1a; s…

制造执行系统(MES)在汽车行业中的应用

汽车行业在不断发展中仍然面临一些挑战和痛点。以下是一些当前汽车行业可能面临的问题&#xff1a; 1.电动化和可持续性转型&#xff1a;汽车行业正逐渐向电动化和可持续性转型&#xff0c;但这需要投入大量资金和资源&#xff0c;包括电池技术、充电基础设施等&#xff0c;同时…

如何判断光模块的收发端

随着光纤通信技术的快速发展&#xff0c;光模块作为光纤通信系统中至关重要的组件&#xff0c;扮演着光信号收发转换器的关键角色&#xff0c;它能够实现光信号的发射和接收功能。为了正确使用光模块并满足通信需求&#xff0c;了解如何准确判断光模块的发射端和接收端显得十分…

SDMMC/SDIO的PCB设计要求

RK3588集成了1个SDMMC控制器和1个SDIO控制器&#xff0c;均可支持SDIO3.0协议&#xff0c; 以及MMC V4.51协议。4线的数据总线宽度&#xff1b;支持SDR104 模式&#xff0c;速率达到150MHz。 SD/MMC或者SDMMC是数字安全记忆卡&#xff08;Secure Digital Memory Card&#xff…

员工矩阵号短视频saas管理系统---开发工具

一、短视频矩阵号系统源码开发层面如何来解决&#xff1f; 1.短视频矩阵号系统源码搭建中&#xff0c;首先开发者需要保证api接口的稳定性 &#xff0c;保证权限应用场景满足官方平台的开发预期。api---待发布、用户管理与授权绑定、私信回复与评论管理等是非常重要的权限接口…

Hutool:WeakCache导致的内存泄漏

闲聊 感谢各位居然有生之年上了一次榜单。没想到一次bug定位这么火&#xff0c;身为电商网站的后台开发&#xff0c;别的不敢说&#xff0c;jvm调优啊&#xff0c;bug定位啊&#xff0c;sql调优啊简直是家&#xff08;ri&#xff09;常&#xff08;chang&#xff09;便&#xf…

LeetCode——二叉树篇(九)

刷题顺序及思路来源于代码随想录&#xff0c;网站地址&#xff1a;https://programmercarl.com 目录 669. 修剪二叉搜索树 108. 将有序数组转换为二叉搜索树 538. 把二叉搜索树转换为累加树 669. 修剪二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界…

用好「留存」,闭环小程序运营链路

如何通过线上小程序获取用户线索&#xff0c;提高企业抗风险能力&#xff0c;建立有效的营销数字化系统一直是困扰每一个小程序开发者与运营者的问题。 当我们选择使用小程序设计自己的运营流程时&#xff0c;从「推广」到「转化」&#xff0c;再到最终的「留存」都是运营过程…

leetcode 1035. 不相交的线

2023.8.25 本题可以转化为&#xff1a;求两数组的最长公共子序列。 进而可以用dp算法解决。 方法类似于这题最长公共子序列 。 代码如下&#xff1a; class Solution { public:int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {vector<…

汽车电子笔记之:AUTOSA架构下的多核OS操作系统

目录 1、AUTOSAR多核操作系统 1.1、OS Application 1.2、多核OS的软件分区 1.3、任务调度 1.4、核间任务同步 1.5、计数器、报警器、调度表 1.6、自旋锁与共享资源 1.7、核间通信IOC 1.8、OS Object中元素交互 1.9、多核OS的启动与关闭 2、多核OS注意事项 2.1、最小…

Classic AUTOSAR专题| 诊断模块(上)

往期小怿向各位小伙伴介绍了Classic AUTOSAR专题之I/O模块&#xff0c;相信看过的小伙伴对Classic AUTOSAR的I/O模块已经有基本的认知了&#xff0c;本期为大家介绍《AUTOSAR模块之诊断模块》&#xff0c;内容超丰富&#xff0c;将分两期推出哦。 目录 1.概述 2.DCM 3.DEM …

upgrade pip报错:def read(rel_path: str) -> str: syntaxerror

命令行执行以下命令就可以大功告成! wget https://bootstrap.pypa.io/pip/2.7/get-pip.py python get-pip.py pip install --upgrade setuptools最后大功告成:

微信小程序基于移动端的个人博客系统的设计与实现

博客系统是能够让网民记录分享和学习的一个网站&#xff0c;在博客中我们可以发表文章对感兴趣的事情进行讨论。而基于移动端的个人博客系统的设计是就为了迎合广大用户需求创建的一个界面简洁、有定向内容、业务逻辑简单易操作的博客系统。本文以博客系统的设计与实现为例&…

【Axure教程】调用日期选择器并筛选中继器表格

今天教大家在Axure里怎么调用代码调用浏览器的日期选择器并对对中继器表格进行日期区间的筛选。调用浏览器日期选择器的好处是&#xff0c;可以选择真实的日期&#xff0c;包括某年某月某日是星期几&#xff0c;哪个二月是29天……都是真实的&#xff0c;那不同的浏览器日期选择…

腾讯云服务器多少钱一年?一个月或1小时费用价格明细表

腾讯云服务器租用费用表&#xff1a;轻量应用服务器2核2G4M带宽112元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、云服务器CVM S5实例2核2G配置280.8元一年、GPU服务器GN10Xp实例145元7天&#xff0c;腾讯云服务器网长期更新腾讯云轻量…

vs2017 错误 RC1015 cannot open include file ‘afxres.h‘.

问题场景&#xff1a; WINDOWS在VS2017环境下编译项目&#xff0c;报错vs2017 错误 RC1015 cannot open include file ‘afxres.h’. 问题排查&#xff1a; 首先&#xff0c;定位到include的文件目录&#xff0c;发现没有这个头文件&#xff1a; 解决方法&#xff1a; 第一种…

【java】【springboot】【idea】springboot项目pom.xml 灰色下划线

解决方案&#xff1a; 这里我们找到了原因&#xff0c;就是因为选择了Ignored Files导致pom.xml文件被设置在maven忽略文件清单中&#xff0c;所以我们将打勾的选项取消&#xff0c;点击Apply,然后点击OK