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; } } } } }

浙公网安备 33010602011771号