vue3实现日历日期选择(不使用任何插件,纯javaScript实现)

个人项目地址: SubTopH前端开发个人站

(自己开发的前端功能和UI组件,一些有趣的小功能,感兴趣的伙伴可以访问,欢迎提出更好的想法,私信沟通,网站属于静态页面)

SubTopH前端开发个人站icon-default.png?t=N7T8https://subtop.gitee.io/subtoph.github.io/#/home

以上 👆 是个人前端项目,欢迎提出您的建议😊

以下是正文内容...............

实现效果

实现功能介绍:

  1. 快捷键自定义
  2. 年和月的前进后退
  3. 选中日期格式的返回,包含格式化日期和时间戳和选择类型
  4. 限制最小和最大日期的选择范围

下面是日期选择组件完整代码


<template><div class="timebox"><div class="shortcut" v-if="timeCount.length"><pv-for="(item, index) in timeCount":key="index"@click="jumpShortcut(item.timeDiff)">{{ item.title }}</p></div><!-- 日历部分--><div id="calendar"><!-- 年份  --><div class="month"><!-- 时间切换 --><div class="time-switch"><!-- 上一年 --><divclass="arrow hands iconfont icon-xiangzuo"@click="pickPre(currentYear, currentMonth, 'Y')"></div><!-- 上个月 --><divclass="arrow hands iconfont icon-xiangzuodan"@click="pickPre(currentYear, currentMonth)"></div><div class="year-month"><span class="choose-year">{{ currentYear }} 年 </span><span class="choose-month">{{ currentMonth }} 月 </span></div><!-- 下个月 --><divclass="arrow hands iconfont icon-xiangyoudan"@click="pickNext(currentYear, currentMonth)"></div><!-- 下一年 --><divclass="arrow hands iconfont icon-xiangyou"@click="pickNext(currentYear, currentMonth, 'Y')"></div></div></div><!-- 星期 --><ul class="weekdays"><li>日</li><li>一</li><li>二</li><li>三</li><li>四</li><li>五</li><li>六</li></ul><!-- 日期 --><div class="days"><!-- 核心 v-for循环 每一次循环用<li>标签创建一天 --><div v-for="dayobject in days" :key="dayobject" class="days-item"><!--不是本月day--><divv-if="dayobject.day.getMonth() + 1 != currentMonth"class="other-day":class="{prohibit:(minTime && dayobject.day.getTime() < minTime) ||(maxTime && dayobject.day.getTime() > maxTime)}"@click="getDayTime(dayobject.day)"><p>{{ dayobject.day.getDate() }}</p></div><!--本月day--><div class="current-month" v-else><divclass="item-day"@click="getDayTime(dayobject.day)":class="[newDate == formatDateYMD(dayobject.day) ? 'active' : '',{prohibit:(minTime && dayobject.day.getTime() < minTime) ||(maxTime && dayobject.day.getTime() > maxTime)}]"><p>{{ dayobject.day.getDate() }}</p></div></div></div></div></div></div>
</template><script>
import { reactive, toRefs, onBeforeMount, onMounted } from 'vue';
export default {name: '',props: {isCompletionZero: {type: Boolean,default: true,explain: '是否补齐日期中各位字符前的0',otherVal: 'false'},dateFormat: {type: String,default: 'Ch',explain: '日期拼接格式(Ch是年月日格式,或者设置拼接符号)',otherVal: '- :/'},minTime: {type: Number,default: 0,explain: '限制可切换的最小时间',otherVal: '时间戳'},maxTime: {type: Number,default: 0,explain: '限制可切换的最大时间',otherVal: '时间戳'},shortcutMenu:{type: Array,default: ()=>{return []},explain: '快捷菜单配置(title:快捷键名称,timeDiff:时间偏移量)',otherVal: `[{ title: '今天', timeDiff: 0 }{ title: '昨天', timeDiff: 偏移的时间戳 }]` },dateChange:{type: Function,explain: `获取选择的日期(format:当前选择的格式化日期,stamp:当前选择时间戳,type:'选择类型点击或者快捷')`}},setup(props,ctx) {const data = reactive({timeCount: [], //时间快捷currentDay: 1,currentMonth: 1,currentYear: 2023, //当前年currentWeek: 1,days: [],newDate: '' //当前日期});onBeforeMount(() => {});onMounted(() => {data.timeCount = props.shortcutMenudata.newDate = formatDateYMD(new Date());});// 初始日期const initData = (cur) => {// let leftcount = 0 // 存放剩余数量let date;if (cur) {date = new Date(cur);} else {const now = new Date();const d = new Date(formatDate(now.getFullYear(), now.getMonth(), 1));d.setDate(35);date = new Date(formatDate(d.getFullYear(), d.getMonth() + 1, 1));}data.currentDay = date.getDate();data.currentYear = date.getFullYear();data.currentMonth = date.getMonth() + 1;data.currentWeek = date.getDay(); // 1...6,0if (data.currentWeek === 0) {data.currentWeek = 7;}let str = formatDate(data.currentYear,data.currentMonth,data.currentDay);data.days.length = 0;// 今天是周日,放在第一行第7个位置,前面6个// 初始化本周for (let i = data.currentWeek; i >= 0; i--) {let d2 = new Date(str);d2.setDate(d2.getDate() - i);let dayobjectSelf = {}; // 用一个对象包装Date对象  以便为以后预定功能添加属性dayobjectSelf.day = d2;data.days.push(dayobjectSelf); // 将日期放入data 中的days数组 供页面渲染使用}// 其他周for (let j = 1; j < 42 - data.currentWeek; j++) {let d3 = new Date(str);d3.setDate(d3.getDate() + j);let dayobjectOther = {};dayobjectOther.day = d3;data.days.push(dayobjectOther);}// 下面方法对多余天数进行截取处理// dayListHandle();};// 对天数数据进行多余截取const dayListHandle = () => {// 判断当前日历中是不是包含今天,控制是否显示跳转今日的按键const currentY = new Date().getFullYear();const currentM = new Date().getMonth() + 1;data.showTodayBtn =data.currentYear !== currentY || data.currentMonth !== currentM;// 下面处理多余其他月的天数let frontNum = 0; //前let afterNum = 0; //后data.days.forEach((item, index) => {// 每一项的月份const inCurrentMonth = item.day.getMonth() + 1;const halfLength = data.days.length / 2;if (data.currentMonth === inCurrentMonth) return; // 和当前月份相等就不在执行if (index < halfLength) {frontNum++;} else {afterNum++;}});if (afterNum < 7 && frontNum < 7) return;if (afterNum > 6) {// console.log('后截取');data.days = data.days.splice(0, data.days.length - 7);}if (frontNum > 6) {// console.log('前截取');data.days = data.days.splice(7);}// 最终展示的天数 42、35、28三个数量// console.log(data.days);};// 快捷跳转// timeDiff  正负 前后移动的时间戳msconst jumpShortcut = (timeDiff) => {let thenTime = new Date();// 计算需要跳转的时间戳thenTime.setTime(thenTime.getTime() + timeDiff);if ((props.minTime && thenTime.getTime() < props.minTime) ||(props.maxTime && thenTime.getTime() > props.maxTime))return;// 根据跳转的时间切换日历const currentY = thenTime.getFullYear();const currentM = thenTime.getMonth() + 1;pickNext(currentY, currentM - 1);data.newDate = formatDateYMD(thenTime); //例如:2023年2月23日console.log('快捷', data.newDate);console.log('快捷时间戳', thenTime.getTime());ctx.emit('dateChange',{format:data.newDate,stamp:thenTime.getTime(),type:'shortcut'})};// 点击日期const getDayTime = (el) => {let timeMs = el.getTime();// 判断时间选择控制范围if ((props.minTime && timeMs < props.minTime) ||(props.maxTime && timeMs > props.maxTime))return;data.newDate = formatDateYMD(el);// 点击其他月份直接跳转,到指定月份if (data.currentMonth < el.getMonth() + 1) {pickNext(data.currentYear, data.currentMonth);}if (data.currentMonth > el.getMonth() + 1) {pickPre(data.currentYear, data.currentMonth);}console.log('手动点击', data.newDate);console.log('手动点击时间戳', timeMs);ctx.emit('dateChange',{format:data.newDate,stamp:timeMs,type:'click'})};// 上个月const pickPre = (year, month, type) => {let m = month;let y = year;if (type === 'Y') {y -= 1;} else {if (m === 1) {y -= 1;m = 12;} else {m -= 1;}}initData(formatDate(y, m, 1));};// 下个月const pickNext = (year, month, type) => {let m = month;let y = year;if (type === 'Y') {y += 1;} else {if (m === 12) {y += 1;m = 1;} else {m += 1;}}initData(formatDate(y, m, 1));};// 返回 类似 2022-05-17 格式的字符串const formatDate = (year, month, day) => {let y = year;let m = month;if (m < 10) m = '0' + m;let d = day;if (d < 10) d = '0' + d;return y + '-' + m + '-' + d;};// 日期格式化,个位数不增加0,2023年2月7日const formatDateYMD = (date) => {let y = date.getFullYear();let m = date.getMonth() + 1;let d = date.getDate();// 是否补齐0if (props.isCompletionZero) {m = m < 10 ? '0' + m : m;d = d < 10 ? '0' + d : d;}// 年月日拼接符号// 默认年月日let returnDate = `${y}年${m}月${d}日`;if (props.dateFormat !== 'Ch') {// 符号拼接const symbol = props.dateFormat;returnDate = `${y}${symbol}${m}${symbol}${d}`;}return returnDate;};// 判断是不是今天const isToday = (day) => {return (day.getFullYear() == new Date().getFullYear() &&day.getMonth() == new Date().getMonth() &&day.getDate() == new Date().getDate());};initData(null);return {jumpShortcut,pickPre,pickNext,getDayTime,isToday,formatDateYMD,...toRefs(data)};}
};
</script>
<style scoped lang="less">
.timebox {// width: 600px;background: #fff;overflow: hidden;display: flex;.shortcut {width: 100px;font-size: 14px;line-height: 26px;padding: 10px;box-sizing: border-box;color: #606266;border-right: 1px solid #ddd;cursor: pointer;transition: 0.3s;p {&:hover {transform: scale(1.05);color: @TSB;}}}#calendar {width: 320px;padding: 10px 20px;cursor: pointer;background: #fff;border-radius: 5px;.month {width: 100%;font-size: 16px;overflow: hidden;.time-switch {display: flex;height: 26px;line-height: 26px;.year-month {flex: 4;text-align: center;width: 200px;color: #606266;}.arrow {flex: 1;font-size: 14px;text-align: center;opacity: 0.5;&:hover {opacity: 1;}}}}.weekdays {overflow: hidden;padding: 10px 0;line-height: 20px;border-bottom: 1px solid @HSE;display: flex;justify-content: space-between;flex-wrap: wrap;li {width: 14%;float: left;text-align: center;color: #606266;font-size: 12px;}}.days {overflow: hidden;display: flex;justify-content: space-between;flex-wrap: wrap;.days-item {width: 14%;height: 40px;float: left;text-align: center;color: #606266;box-sizing: border-box;font-size: 12px;transition: 0.3s;line-height: 40px;position: relative;&:hover {color: @TSB;}.item-day,.other-day {height: 100%;box-sizing: border-box;transition: 0.3s;height: 30px;line-height: 30px;margin-top: 5px;&.active {p {margin: 0 auto;width: 30px;border-radius: 20px;background: @TSB;color: #fff;}}&.prohibit {background: @TSD;color: @HSD;}}.current-month {height: 100%;}.other-day {color: @HSD;}}}}
}
</style>

上面代码直接创建vue文件,在其他文件直接引入组件使用即可

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

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

相关文章

中东 Shopify 如何使用 Bytebase 构建一站式数据库开发工作流

公司简介 Salla 是一家 2016 年成立&#xff0c;位于沙特麦加的自建站电商平台。 作为中东 Shopify&#xff0c;其最大的特点是支持阿拉伯语建站&#xff0c;并且提供更多适应中东地区特点的本地化服务。截止目前&#xff0c;已有 47,000 家店铺入驻 Salla&#xff0c;商品销售…

【前端demo】将二进制数转换为十进制数 原生实现

https://github.com/florinpop17/app-ideas 总结 文章目录 效果JavaScript实现进制转换原生代码遇到的问题 效果 二进制转换为十进制若输入为空或不是二进制&#xff0c;提示清空 https://codepen.io/karshey/pen/dywXZYQ JavaScript实现进制转换 parseInt parseInt(111,…

《Kali渗透基础》15. WEB 渗透

kali渗透 1&#xff1a;WEB 技术1.1&#xff1a;WEB 攻击面1.2&#xff1a;HTTP 协议基础1.3&#xff1a;AJAX1.4&#xff1a;WEB Service 2&#xff1a;扫描工具2.1&#xff1a;HTTrack2.2&#xff1a;Nikto2.3&#xff1a;Skipfish2.4&#xff1a;Arachni2.5&#xff1a;OWAS…

前端面试必备 | uni-app 篇(P1-15)

文章目录 1. 请简述一下uni-app的定义和特点。2. uni-app兼容哪些前端框架&#xff1f;请列举几个。3. 请简述一下uni-app的跨平台工作原理。4. 什么是条件编译&#xff1f;在uni-app中如何实现条件编译&#xff1f;5. uni-app中的页面生命周期有哪些&#xff1f;请简要介绍。6…

UG\NX CAM二次开发 插入工序 UF_OPER_create

文章作者:代工 来源网站:NX CAM二次开发专栏 简介: UG\NX CAM二次开发 插入工序 UF_OPER_create 效果: 代码: void MyClass::do_it() {tag_t setup_tag=NULL_TAG;UF_SETUP_ask_setup(&setup_tag);if (setup_tag==NULL_TAG){uc1601("请先初始化加工环境…

【计算机网络】OSI 七层网络参考模型

OSI&#xff08;Open Systems Interconnection&#xff09;七层网络参考模型是一种用于描述计算机网络通信的框架&#xff0c;将网络通信划分为七个不同的层次&#xff0c;每个层次负责不同的功能。 以下为 OSI 七层网络参考模型的简单表格&#xff1a; --------------------…

maven的依赖下载不下来的几种解决方法

前言 每次部署测试环境&#xff0c;从代码库拉取代码&#xff0c;都会出现缺少包的情况。然后找开发一通调试&#xff0c;到处拷包。 方案一&#xff1a;pom文件注释/取消注释 注释掉pom.xml里的报红色的依赖&#xff08;同时可以把本地maven库repo里对应的包删除&#xff09;&…

一款不能错过的Git客户端:Fork for Mac,让你的代码管理更便捷

Fork for Mac是一款强大的Git客户端&#xff0c;让用户在Mac电脑上更方便地进行版本控制和代码管理。它具有以下特点&#xff1a; 易用性&#xff1a;Fork for Mac界面简洁明了&#xff0c;操作简单易懂&#xff0c;让用户可以快速上手。功能强大&#xff1a;支持各种Git功能&…

Mac软件删除方法?如何删除不会有残留

Mac电脑如果有太多无用的应用程序&#xff0c;很有可能会拖垮Mac系统的运行速度。因此&#xff0c;卸载电脑中无用的软件是优化Mac系统运行速度的最佳方式之一。Mac卸载应用程序的方式是和Windows有很大的区别&#xff0c;特别对于Mac新用户来说&#xff0c;如何无残留的卸载删…

【Latex】使用技能站:(三)使用 Vscode 配置 LaTeX

使用 Vscode 配置 LaTeX 引言1 安装texlive2 安装vscode2.1 插件安装2.2 配置 3 安装SumatraPdf3.1 vscode配置3.2 配置反向搜索 引言 安装texlive 安装vscode 安装SumatraPdf 1 安装texlive 在线LaTeX编辑器&#xff1a;https://www.overleaf.com TeX Live下载&#xff1a;h…

【LeetCode】《LeetCode 101》第十二章:字符串

文章目录 12.1 字符串比较242 . 有效的字母异位词&#xff08;简单&#xff09;205. 同构字符串&#xff08;简单&#xff09;647. 回文子串&#xff08;中等&#xff09;696 . 计数二进制子串&#xff08;简单&#xff09; 12.2 字符串理解224. 基本计算器&#xff08;困难&am…

Java的23种设计模式

Java的23种设计模式 一、创建型设计模式1.单例模式 singleton1.1.静态属性单例模式1.2 静态属性变种1.3 基础的懒汉模式1.4 线程安全的懒加载单例1.5 线程安全的懒加载 单例-改进1.6 双重检查锁1.7 静态内部类1.8 枚举单例1.9 注册表单例 2.工厂方法模式 factory3.抽象工厂模式…

IE浏览器攻击:MS11-003_IE_CSS_IMPORT

目录 概述 利用过程 漏洞复现 概述 MS11-003_IE_CSS_IMPORT是指Microsoft Security Bulletin MS11-003中的一个安全漏洞&#xff0c;影响Internet Explorer&#xff08;IE&#xff09;浏览器。这个漏洞允许攻击者通过在CSS文件中使用import规则来加载外部CSS文件&#xff0…

51单片机项目(8)——基于51单片机的DS1302时钟系统

本次做的设计&#xff0c;是利用DS1302时钟芯片&#xff0c;做了一个时钟&#xff0c;并且将实时时间通过串口发送到上位机进行显示。系统运行如下&#xff1a;&#xff08;protues文件和相关keil代码会在文章最后给出&#xff01;&#xff01;&#xff01;&#xff09; DS1302…

[ES]二基础 |

一、索引库操作 1、mapping属性 mapping是对索引库中文档的约束&#xff0c;常见的mapping属性包括&#xff1a; 1)type&#xff1a;字段数据类型&#xff0c;常见的简单类型有&#xff1a; ①字符串&#xff1a;text(可分词的文本)、keyword&#xff08;精确值&#xff0c…

【LeetCode每日一题】——274.H指数

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 排序 二【题目难度】 中等 三【题目编号】 274.H指数 四【题目描述】 给你一个整数数组 ci…

Qt无边框青绿色主题

收费产品&#xff0c;学生党、闹眼子党勿扰 收费金额&#xff1a;500元 1 概述 最近因项目需要&#xff0c;写了一个炫酷的青绿色、无边框界面&#xff0c;和3DSMax的界面有点类似。 2 截图 首先看看3DSMax的界面 不知道大家看出来没&#xff0c;这个ui其实很简单&#xff…

ELK安装、部署、调试 (七)kibana的安装与配置

1.介绍 Kibana 是一个基于浏览器的开源可视化工具&#xff0c;主要用于分析大量日志&#xff0c;以折线图、条形图、饼图、热图、区域图、坐标图、仪表、目标、时间等形式。预测或查看输入源的错误或其他重大事件趋势的变化。Kibana 与 Elasticsearch 和 Logstash 同步工作&am…

15年检测生涯转瞬即逝,复旦MBA助力邢国芒实现质量强国梦

日月光华&#xff0c;旦复旦兮&#xff01;复旦MBA如同一个巨大的磁场&#xff0c;吸引了诸多来自五湖四海、各行各业的职场精英。从初入职场的青涩懵懂到如今的独当一面专业干练&#xff0c;他们逐渐成长为职场的中坚力量&#xff0c;在各自领域内发光发热。作为新时代的青年&…

算法 稀疏数组 数组优化 数组压缩 二维数组转稀疏数组 算法合集(二)

1. 五子棋游戏&#xff0c;玩家对战一半停战休息&#xff0c;此时需要存储当前对战双方棋子信息 a. 采用二维数组存储&#xff1a; 0为空&#xff0c; 1代表黑棋 2代表蓝色棋子 b. 棋盘为11行&#xff0c;11列 > int [][] chessArray new int [11][11]; c. 出现的问题&am…