vue写一个自定义日历组件
因为最近需求需要,写一个自定义日历。
废话少说直接上效果图, 日历返回的起始时间
代码实现
首先根据当前月时间 组建日历
构建日历
createTime(){ let t = this; let Timesr = getTime(); t.Timesr = Timesr; t.$nextTick(()=>{ this.optTime(Timesr) }) }, // 到时候需要什么数据改这个函数 optTime(Timesr){ let t = this; let lastDay= new Date(Timesr.y,Timesr.month,0).getDate(); this.weekey = new Date(`${Timesr.y}-${Timesr.month}-01`).getDay(); let arr = [] arr[t.monthIndex] = {Yname:`${Timesr.y}年${Timesr.month}月`,chlid:[]} for(let i = 1; i<=lastDay; i++){ let _o = { day:i, about:Timesr.d > i?1:0, Reducible:Timesr.d >i?1:0, price:i==10?100:0, m:Timesr.month, y:Timesr.y, dayText:`${Timesr.y}-${Timesr.month<=9?'0'+Timesr.month:Timesr.month}-${i<=9?'0'+i:i}` } arr[t.monthIndex].chlid.push(_o) } t.dayList = arr },
完整代码
<template> <view class="day_conter" v-if="isModal" > <view class="day_head"> <view @click="rePath('upper')">上一月</view> <view class="day_tille" >{{dayList[monthIndex].Yname}}</view> <view @click="rePath('next')" >下一月</view> </view> <view class="day-wrap"> <view class="day-tit"> <view class="day-tit-cell" v-for="(item,index) in week" :key="index">{{item}}</view> </view> <view class="day-table"> <view class="day-list-cell" v-for="(item,index) in weekey" :key="index"></view> <view class="day-list-cell" v-for="(item,index) in dayList[monthIndex].chlid" :key="index" :class="[item.about>0?'white':'',(item.dayText && selectDay.includes(item.dayText) )?'act':'']" @click="selectDate(item.about>0?item:'',index)" > <text class="day_about" v-if="!selectDay.includes(item.dayText)" :class="!item.about?'':'day_yabout'">{{!item.about?'已约满':'可预约'}} </text> <tex class="day_about" v-if="mode==true&&selectDay.length>0">{{selectDay[0]==item.dayText?'入住':selectDay[selectDay.length-1]==item.dayText?'离店':selectDay[index]==item.dayText?'选中':''}}</tex> <text class="day-list-cell-day">{{item.day}}</text> <text class="day-list-cell-price" v-if="item.about&&item.price">补差¥{{item.price}}</text> </view> </view> </view> </view> </template> <script> import { getTime } from '../../untils/index.js' export default{ props:{ isModal:{ type:Boolean, default:false }, mode:{ //单多选 type:Boolean, default:true } }, data(){ return{ week:['日','一','二','三','四','五','六'], weekey:0, dayList:[], monthIndex:0, Timesr:'', opt:[], selectDay:[], //选中的 } }, created(){ this.createTime() }, watch:{ Timesr:{ deep:true, handler(val){ this.optTime(val) } } }, methods:{ init(){ let t = this; t.createTime() }, // 初始化日历根据当前月组建日历 createTime(){ let t = this; let Timesr = getTime(); t.Timesr = Timesr; t.$nextTick(()=>{ this.optTime(Timesr) }) }, // 到时候需要什么数据改这个函数 optTime(Timesr){ let t = this; let lastDay= new Date(Timesr.y,Timesr.month,0).getDate(); this.weekey = new Date(`${Timesr.y}-${Timesr.month}-01`).getDay(); let arr = [] arr[t.monthIndex] = {Yname:`${Timesr.y}年${Timesr.month}月`,chlid:[]} for(let i = 1; i<=lastDay; i++){ let _o = { day:i, about:Timesr.d > i?1:0, Reducible:Timesr.d >i?1:0, price:i==10?100:0, m:Timesr.month, y:Timesr.y, dayText:`${Timesr.y}-${Timesr.month<=9?'0'+Timesr.month:Timesr.month}-${i<=9?'0'+i:i}` } arr[t.monthIndex].chlid.push(_o) } t.dayList = arr }, //上下一个月 rePath(o){ let t = this; let opt = t.Timesr t.selectDay = [] t.opt = [] if(o == 'upper'){ opt.month-- if( opt.month==0 ){ opt.month = 12 opt.y-- } }else{ opt.month++ if( opt.month>12 ){ opt.month = 1 opt.y++ } } }, //随便乱选 selectDate(Node){ let opt = this.opt; let arr = this.selectDay; let t = this; if(Node){ if(!this.mode){ //单选 t.selectDay = [Node.dayText] t.$emit('select',Node) }else{ //开始 if(arr.length>0&&arr.includes(Node.dayText)){ if(arr.length>1){ arr.map((item,indexs)=>{ if(item == Node.dayText ){ opt[1] = {... Node} } }) }else{ arr = arr.filter(item=>{ return item !== Node.dayText }) opt = [] t.opt = [] } } else{ arr.push(Node.dayText); if( arr.length==1 ){ opt[0] = {...Node } }else if(arr.length>1){ opt[1] = {...Node} } } t.selectDay = arr if(opt.length == 2){ t.FnTime(opt,arr) } } } }, // 多选特效 FnTime(Node,list){ let t = this; let arr = []; let num = 0; let isNum=false if(Node[1].day>Node[0].day ){ num = Node[1].day-Node[0].day; isNum=true }else{ num = Node[0].day-Node[1].day; isNum=false } let o = new Array(num); for( let i =0; i <= o.length;i++){ arr.push( `${isNum?Node[0].y:Node[1].y}-${isNum?Node[0].m<=9?'0'+Node[0].m:Node[0].m:Node[1].m<=9?'0'+Node[1].m:Node[1]}-${isNum?(Node[0].day+i)<=9?'0'+(Node[0].day+i):(Node[0].day+i):(Node[1].day+i)<=9?'0'+(Node[1].day+i):(Node[1].day+i)}` ) } t.selectDay = arr if(!isNum){ Node.reverse() } t.$emit('select',Node) //返回 选中起始时间 } } } </script> <style lang="scss"> @import "./index.scss" </style>
css 如下
.day_conter { max-height: 75vh; overflow-y: auto; //background: #FCFCFC; padding-bottom: calc(116rpx + env(safe-area-inset-bottom)); position: relative; width: 750rpx; border-radius: 24rpx 24rpx 0 0; padding: 20rpx 0 300rpx 0; margin-top: 20rpx; .day_head { display: flex; height: 82rpx; justify-content: center; line-height: 82rpx; background: #FFFFFF; border-bottom: 1rpx solid #EEEEEE; .day_tille { padding: 0 20rpx; } } .day-wrap { //padding-bottom: 16rpx; background: #FFFFFF; width: 100%; position: relative; .day-tit { display: flex; justify-content: flex-start; .day-tit-cell { width: 14.25%; box-sizing: border-box; height: 82rpx; background-color: #FFFFFF; font-size: 24rpx; font-family: Microsoft YaHei; font-weight: 400; text-align: center; color: #333333; display: flex; justify-content: center; flex-flow: column; } .day-tit-cell:nth-of-type(1) { color: #FF7920; } } .day-table { display: flex; justify-content: flex-start; flex: 1; flex-direction: row; flex-wrap: wrap; font-size: 18rpx; .day-list-cell { width: 14.26%; height: 120rpx; box-sizing: border-box; border-top: 2rpx solid #F6F6F6; border-bottom: 2rpx solid #F6F6F6; display: flex; justify-content: flex-start; flex-flow: column; padding-top: 12rpx; background: #F9F9F9; border-right: 1rpx solid #FFFFFF; .day_about { text-align: center; font-weight: bold; display: block; font-size: 20rpx; } .day-Reducible { text-align: center; } .day-list-cell-day { text-align: center; font-size: 28rpx; font-family: PingFang SC; font-weight: 400; line-height: 43rpx; color: #333333; } .day-list-cell-price { text-align: center; font-size: 16rpx; font-family: PingFang SC; font-weight: bold; line-height: 20rpx; color: #FF7920; } } .day-list-cell.white { background: #FFFFFF; } .day_yabout { // 可预约 color: #9BD588; } .day_man { color: #999; } .day_less { // 紧张 color: #FF7920; } .day-list-cell.act { background: #3685FC; border-radius: 16rpx 0rpx 0rpx 16rpx; .day-list-cell-day { color: #FFFFFF; } .day_about { color: #fff; } .day-list-cell-price { color: #FFFFFF; } } .day-list-cell.acts { background: #3685FC; border-radius: 0rpx 16rpx 16rpx 0rpx; .day-list-cell-day { color: #FFFFFF; } .day_about { color: #fff; } .day-list-cell-price { color: #FFFFFF; } } .day-list-cell.actdan { background: #EAF1FE; .day-list-cell-day { color: #A5CEFF; } .day_about { color: #A5CEFF; } .day-list-cell-price { color: #A5CEFF; } } .day-list-cell.actives { background: #3685FC; border-radius: 16rpx; .day-list-cell-day { color: #FFFFFF; } .day_about { color: #fff; } .day-list-cell-price { color: #FFFFFF; } } } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现