vue横向滚动日期选择器组件

news2024/12/20 12:01:10

vue横向滚动日期选择器组件

组件使用到了element-plus组件库和dayjs库,使用前先保证项目中已经下载导入

主要功能:选择日期,点击日期可以让此日期滚动到视图中间,左滑右滑同理,支持跳转至任意日期,支持自定义滚动日期的数量

组件中用到了other.ts
工具代码other.ts

import dayjs from 'dayjs'
import calendar from 'dayjs/plugin/calendar'
import 'dayjs/locale/zh-cn'

dayjs.locale('zh-cn')
dayjs.extend(calendar)
dayjs().calendar(null, {
  sameDay: '[Today]', // The same day ( Today at 2:30 AM )
  nextDay: '[Tomorrow]', // The next day ( Tomorrow at 2:30 AM )
  nextWeek: 'dddd', // The next week ( Sunday at 2:30 AM )
  lastDay: '[Yesterday]', // The day before ( Yesterday at 2:30 AM )
  lastWeek: '[Last]', // Last week ( Last Monday at 2:30 AM )
  sameElse: 'DD/MM/YYYY' // Everything else ( 7/10/2011 )
})

function judegSame(dj1: dayjs.Dayjs, dj2: dayjs.Dayjs) {
  return dj1.isSame(dj2)
}

function getRelativeTime(dj: dayjs.Dayjs) {
  let now = dayjs(dayjs().format('YYYY-MM-DD'))
  if (judegSame(now, dj)) {
    return '今天'
  }
  now = now.add(1, 'day')
  if (judegSame(now, dj)) {
    return '明天'
  }
  now = now.add(1, 'day')
  if (judegSame(now, dj)) {
    return '后天'
  }
  let d = dj.day()
  const backArr = ['日', '一', '二', '三', '四', '五', '六']
  return '周' + backArr[d]
}

export { dayjs, getRelativeTime }

组件代码SlideDatePicker.vue

<script setup lang="ts">
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
import { dayjs, getRelativeTime } from './other';

// 日期加载总量
const { count } = withDefaults(defineProps<{
  count: number
}>(), {
  count: 30
})
const activeIndex = ref(0)
const dateItemRefs = ref<HTMLElement[]>([])
const dateItmeWrapRef = ref<HTMLElement>()
const curDate = ref('') // 日期选择器 选择的日期

const showDateList = ref<Record<string, any>[]>([])

const emit = defineEmits(['dateChange'])

function calc(format?: string) {
  if (!format) {
    format = dayjs().format('YYYY-MM-DD')
  }
  showDateList.value = []
  let beforeCount = Math.floor((count + 1) / 2) // 上取整
  let afterCount = Math.floor(count / 2)
  let cur = dayjs(dayjs(format).format('YYYY-MM-DD'))
  for (let i = 0; i < beforeCount; i++) {
    showDateList.value.push({
      date: cur.format('YYYYMMDD'),
      dateMd: cur.format('MMDD'),
      week: getRelativeTime(cur)
    })
    cur = cur.subtract(1, 'day')
  }
  showDateList.value = showDateList.value.reverse() // 反转 让最早的日期排在第一位
  cur = dayjs(dayjs(format).format('YYYY-MM-DD'))
  for (let i = 0; i < afterCount; i++) {
    cur = cur.add(1, 'day')
    showDateList.value.push({
      date: cur.format('YYYYMMDD'),
      dateMd: cur.format('MMDD'),
      week: getRelativeTime(cur)
    })
  }
}

const getMiddle = computed(() => {
  return Math.floor((showDateList.value.length + 1) / 2) - 1
})

function move(step: number) {
  // 越界无效
  if (activeIndex.value + step >= showDateList.value.length || activeIndex.value + step < 0) {
    return
  }
  activeIndex.value += step
  dateItmeWrapRef.value?.scrollTo({
    behavior: 'smooth',
    left: (dateItemRefs.value[activeIndex.value].offsetLeft - dateItmeWrapRef.value.offsetWidth / 2)
  })
  curDate.value = dayjs(showDateList.value[activeIndex.value].date, 'YYYYMMDD').format('YYYY-MM-DD')
  emit('dateChange', curDate.value)
}

function moveToIndex(index: number) {
  if (index >= showDateList.value.length || index < 0) {
    return
  }
  activeIndex.value = index
  dateItmeWrapRef.value?.scrollTo({
    behavior: 'smooth',
    left: (dateItemRefs.value[activeIndex.value].offsetLeft - dateItmeWrapRef.value.offsetWidth / 2)
  })
  curDate.value = dayjs(showDateList.value[activeIndex.value].date, 'YYYYMMDD').format('YYYY-MM-DD')
  emit('dateChange', curDate.value)
}

function datePickerChange(value: string) {
  // 重新计算
  curDate.value = dayjs(value).format('YYYY-MM-DD')
  calc(curDate.value)
  activeIndex.value = getMiddle.value
  nextTick(() => {
    dateItmeWrapRef.value?.scrollTo({
      behavior: 'instant',
      left: (dateItemRefs.value[activeIndex.value].offsetLeft - dateItmeWrapRef.value.offsetWidth / 2)
    })
  })
  emit('dateChange', curDate.value)
}

onMounted(() => {
  calc()
  activeIndex.value = getMiddle.value
  curDate.value = dayjs().format('YYYY-MM-DD')
  nextTick(() => {
    dateItmeWrapRef.value?.scrollTo({
      behavior: 'instant',
      left: (dateItemRefs.value[activeIndex.value].offsetLeft - dateItmeWrapRef.value.offsetWidth / 2)
    })
  })
})

</script>

<template>
  <div class="date_picker_wrap">
    <div class="left_icon">
      <el-button :icon="ArrowLeft" link @click="move(-1)">
      </el-button>
    </div>
    <div class="date_item_wrap" ref="dateItmeWrapRef">
      <div class="date_item" :class="index === activeIndex ? 'active' : ''" v-for="(item, index) in showDateList"
        ref="dateItemRefs" @click="moveToIndex(index)">
        <span>{{ item.dateMd }}</span>
        <span>{{ item.week }}</span>
      </div>
    </div>
    <div class="right_icon">
      <el-button :icon="ArrowRight" link @click="move(1)">
      </el-button>
    </div>
    <div class="calendar_icon">
      <el-date-picker style="width: 126px;" v-model="curDate" type="date" placeholder="选择日期" format="YYYY-MM-DD"
        :clearable="false" @change="datePickerChange" />
    </div>
  </div>
</template>

<style scoped>
.date_picker_wrap {
  background: #fff;
  width: 100%;
  height: 52px;
  border-radius: 6px;
  padding: 4px 8px;
  display: flex;
  align-items: center;
  font-size: 14px;
  color: #4b5563;

  .date_item_wrap {
    width: 100%;
    display: flex;
    flex: 1;
    overflow: hidden;

    .active {
      color: #3c6cfe;
    }

    .date_item {
      padding: 0 6px;
      width: 96px;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      border-left: solid 1px #e5e7eb;
      border-right: solid 1px #e5e7eb;
      cursor: pointer;

      &:hover {
        color: #3c6cfe;
      }

      span {
        padding: 0 2px;
      }
    }
  }

  .left_icon,
  .right_icon,
  .calendar_icon {
    padding: 0 8px;
  }
}
</style>

使用方式

传入count 30,组件初始化横向滚动日期数为30个,初始化数量不要太少,最好占满宽度,让其可以滚动。

<SlideDatePicker :count="30" @dateChange="dateChange" />
function dateChange(value: string) {
  console.log('选中的日期', value); // 2024-12-19
}

效果图
在这里插入图片描述

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

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

相关文章

Firecrawl教程①:自动化抓取与数据转化,赋能AI应用

Firecrawl教程①:自动化抓取与数据转化,赋能AI应用 前言一、功能特点1. 支持 LLM 可处理的数据格式2. 全面抓取网站3. 强大的操作支持4. 灵活的定制选项5. 支持多种编程语言 SDK二、如何开始使用 Firecrawl第一步:获取 API 密钥第二步:官网在线工具使用第三步:安装 Firecr…

WatchAlert - 开源多数据源告警引擎

概述 在现代 IT 环境中&#xff0c;监控和告警是确保系统稳定性和可靠性的关键环节。然而&#xff0c;随着业务规模的扩大和数据源的多样化&#xff0c;传统的单一数据源告警系统已经无法满足复杂的需求。为了解决这一问题&#xff0c;我开发了一个开源的多数据源告警引擎——…

svn版本丢失导致无法访问临时解决方法

#svn异常问题# 在使用svn的过程中&#xff0c;有时候在数据量比较大的情况下&#xff0c;有涉及到数据迁移或者是文件移动操作时容易出现迁移过程中有人还提交了数据&#xff0c;导致迁移的数据出现版本丢失的情况。 比如说&#xff0c;我实际遇到的情况是迁移数据的时候记录…

0009.基于springboot+layui的ERP企业进销存管理系统

一、系统说明 基于springbootlayui的ERP企业进销存管理系统,系统功能齐全, 代码简洁易懂&#xff0c;适合小白学编程,课程设计&#xff0c;毕业设计。 二、系统架构 前端&#xff1a;html| layui 后端&#xff1a;springboot | mybatis| thymeleaf 环境&#xff1a;jdk1.8 |…

Latex+VsCode+Win10搭建

最近在写论文&#xff0c;overleaf的免费使用次数受限&#xff0c;因此需要使用本地的形式进行编译。 安装TEXLive 下载地址&#xff1a;https://mirror-hk.koddos.net/CTAN/systems/texlive/Images/ 下载完成直接点击iso进行安装操作。 安装LATEX Workshop插件 设置VsCode文…

[创业之路-199]:《华为战略管理法-DSTE实战体系》- 3 - 价值转移理论与利润区理论

目录 一、价值转移理论 1.1. 什么是价值&#xff1f; 1.2. 什么价值创造 &#xff08;1&#xff09;、定义 &#xff08;2&#xff09;、影响价值创造的因素 &#xff08;3&#xff09;、价值创造的三个过程 &#xff08;4&#xff09;、价值创造的实践 &#xff08;5&…

如何在单选按钮中添加图标和文字

文章目录 1. 概念介绍2. 使用方法3. 示例代码我们在上一章回中介绍了Radio Widget相关的内容,本章回中将介绍RadioListTile Widget.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里介绍的RadioListTile和上一章回中介绍的Radio类似,不同之处在于RadioListTile组…

启动异常:Caused by: java.lang.IllegalStateException: Failed to introspect Class

背景 今天项目需要&#xff0c;导入一个本地的jar包&#xff0c;在pom文件&#xff0c;添加自定义依赖后&#xff0c;并通过mvn命令&#xff1a; mvn install:install-file -Dfilejar包的位置 -DgroupId自定义的groupId -DartifactId自定义的artifactId -Dversion自定义的ver…

clickhouse-副本和分片

1、副本 1.1、概述 集群是副本和分片的基础&#xff0c;它将ClickHouse的服务拓扑由单节点延伸到多个节点&#xff0c;但它并不像Hadoop生态的某些系统那样&#xff0c;要求所有节点组成一个单一的大集群。ClickHouse的集群配置非常灵活&#xff0c;用户既可以将所有节点组成…

Python机器学习算法KNN、MLP、NB、LR助力油气钻井大数据提速参数优选及模型构建研究...

全文链接&#xff1a;https://tecdat.cn/?p38601 分析师&#xff1a;Huayan Mu 随着机器学习和大数据分析技术的发展&#xff0c;帮助客户进行油气行业数字化转型势在必行&#xff0c;钻井提速参数优选呈现由经验驱动、逻辑驱动向数据驱动转变的趋势。机械钻速最大化、机械比能…

【尚硅谷 - SSM+SpringBoot+SpringSecurity框架整合项目 】项目打包并且本地部署

前后端分离开发&#xff1a;把一个项目拆成两部分进行开发&#xff0c;所以在打包的时候&#xff0c;需要使用不同的打包方式。 后端 – SpringBoot – jar包 前端 – Vue: 因为使用了vue-admin-template框架&#xff1a;所以先使用框架进行打包使用Nginx部署&#xff0c;通…

练13:二分法

欢迎大家订阅【蓝桥杯Python每日一练】 专栏&#xff0c;开启你的 Python数据结构与算法 学习之旅&#xff01; 文章目录 1 二分查找2 例题分析 1 二分查找 ①定义 在计算机科学中&#xff0c;二分算法&#xff08;Binary Search&#xff09;是一种高效的查找算法&#xff0c;…

Android Studio更改项目使用的JDK

一、吐槽 过去&#xff0c;在安卓项目中配置JDK和Gradle的过程非常直观&#xff0c;只需要进入Android Studio的File菜单中的Project Structure即可进行设置&#xff0c;十分方便。 原本可以在这修改JDK: 但大家都知道&#xff0c;Android Studio的狗屎性能&#xff0c;再加…

基于ST STM32MP257FAK3的MP2控制器之工业PLC 方案

简介 1.可编程逻辑控制器&#xff08;PLC&#xff09;是种专门为在工业环境下应用而设计的数字运算操作电子系统。它采用一种可编程的存储器&#xff0c;在其内部存储执行逻辑运算、顺序控制、定时、计数和算术运算等操作的指令&#xff0c;通过数字式或模拟式的输入输出来控制…

唯品会Android面试题及参考答案

HTTP 和 HTTPS 的区别是什么?你的项目使用的是 HTTP 还是 HTTPS? HTTP 和 HTTPS 主要有以下区别。 首先是安全性。HTTP 是超文本传输协议,数据传输是明文的,这意味着在数据传输过程中,信息很容易被窃取或者篡改。比如,在一个不安全的网络环境下,黑客可以通过网络嗅探工具…

黑马Java面试教程_P2_Redis

系列博客目录 文章目录 系列博客目录1前言2 使用场景面试官提问1&#xff1a;我看你做的项目中&#xff0c;都用到了redis&#xff0c;你在最近的项目中哪些场景使用了redis呢?面试官会接着问你1.1&#xff1a;如果发生了缓存穿透、击穿、雪崩&#xff0c;该如何解决?2.1缓存…

Python如何正确解决reCaptcha验证码(9)

前言 本文是该专栏的第73篇,后面会持续分享python爬虫干货知识,记得关注。 我们在处理某些国内外平台项目的时候,相信很多同学或多或少都见过,如下图所示的reCaptcha验证码。 而本文,笔者将重点来介绍在实战项目中,遇到上述中的“reCaptcha验证码”,如何正确去处理并解…

Unity3D仿星露谷物语开发5之角色单例模式

1、目的 使用单例模式创建角色对象&#xff0c;保证整个游戏中只有一个角色&#xff0c;并且让游戏对象具有全局可访问性。 2、流程 &#xff08;1&#xff09;创建SingletonMonobehaviour脚本 Assets下创建Scripts目录用于存放所有的脚本&#xff0c;再创建Misk子目录&…

控制表格向上滚动距离最佳实践(以Element ui为例)

前言 在web开发中&#xff0c;有些时候使用的组件库的表格不支持滚动的属性或方法。这个时候我们就要自己去实现这一功能。在Element Plus里&#xff0c;组件库已经具备了支持滚动表格的属性或方法&#xff0c;但是在支持vue2的element ui里&#xff0c;Table组件本身不提供直…

ubuntu16.04ros-用海龟机器人仿真循线系统

下载安装sudo apt-get install ros-kinetic-turtlebot ros-kinetic-turtlebot-apps ros-kinetic-turtlebot-interactions ros-kinetic-turtlebot-simulator ros-kinetic-kobuki-ftdi sudo apt-get install ros-kinetic-rocon-*echo "source /opt/ros/kinetic/setup.bash…