<template>
<div v-click-outside>
<input type="text" :value="formatDate">
<div v-if="isVisible" class="pannel">
<div class="pannel-nav">
<span @click="prevYear"><</span>
<span @click="prevMonth"><<</span>
<span>{{time.year}}年</span>
<span>{{time.month + 1}}月</span>
<span @click="nextMonth">>></span>
<span @click="nextYear">></span>
</div>
<div class="pannel-content">
<span v-for="(item,index) in week">{{item}}</span>
<div class="days">
<div v-for="i in 6" :key="i">
<span
v-for="j in 7" :key="j"
@click="handleChooseDate(visibleDays[(i-1) * 7 + (j-1)])"
class="cell"
:class="[
{notCurrerntMonth:!isCurrerntMonth(visibleDays[(i-1) * 7 + (j-1)])},
{today: isToday(visibleDays[(i-1) * 7 + (j-1)])},
{select: isSelect(visibleDays[(i-1) * 7 + (j-1)])}
]"
>
{{visibleDays[(i-1) * 7 + (j-1)].getDate()}}
</span>
</div>
</div>
</div>
<div class="pannel-footer">
今天
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Calendar',
directives: {
clickOutside: {
bind(el,bindings,vnode) {
let handler = (e) => {
if(el.contains(e.target)) {
if(!vnode.context.isVisible) {
vnode.context.hanldeFocus()
}
}else {
if(vnode.context.isVisible) {
vnode.context.handleBlur()
}
}
}
el.handler = handler
document.addEventListener('click',handler)
},
unbind(el){
document.removeEventListener('click',el.handler)
}
}
},
data () {
let {year, month} = this.getYearMonthDay(this.value)
return {
week: ['日', '一', '二', '三', '四', '五', '六'],
time: {year,month},
isVisible: false
}
},
props: {
value: {
type: Date,
default: () => new Date()
}
},
mounted() {
console.log(this.visibleDays)
},
computed: {
visibleDays() {
let {year,month} = this.getYearMonthDay(this.getDate(this.time.year,this.time.month, 1))
let currentFirstDay = this.getDate(year,month,1)
let week = currentFirstDay.getDay()
console.log('week',week)
let startDay = currentFirstDay - week * 60 * 60 * 1000 * 24
let arr = []
for(let i = 0; i < 42; i++) {
arr.push(new Date(startDay + i * 60 * 60 * 1000 * 24))
}
return arr
},
formatDate() {
let {year,month,day} = this.getYearMonthDay(this.value)
return `${year}-${month + 1}-${day}`
}
},
methods:{
getYearMonthDay() {
const year = date.getFullYear()
const month = date.getMonth()
const day = date.getDate()
return {year, month, day}
},
getDate(year, month, day) {
return new Date(year, month, day)
},
hanldeFocus() {
this.isVisible = true
},
handleBlur() {
this.isVisible = false
},
isCurrerntMonth(date) {
let {year,month} = this.getYearMonthDay(this.getDate(this.time.year,this.time.month,1))
let {year:y, month:m} = this.getYearMonthDay(date);
return year === y && month === m
},
isToday(date) {
let {year,month,day} = this.getYearMonthDay(new Date())
let {year:y, month:m, day:d} = this.getYearMonthDay(date)
return year === y && month === m && day === d
},
handleChooseDate(date) {
this.time = this.getYearMonthDay(date)
this.$emit('change',date)
this.handleBlur()
},
isSelect(date) {
let {year,month,day} = this.getYearMonthDay(this.value)
let {year:y, month:m, day:d} = this.getYearMonthDay(date)
return year === y && month === m && day === d
},
prevMonth() {
let d = this.getDate(this.time.year,this.time.month,1)
d.setMonth(d.getMonth()-1)
this.time = this.getYearMonthDay(d)
},
nextMonth() {
let d = this.getDate(this.time.year,this.time.month,1)
d.setMonth(d.getMonth() + 1)
this.time = this.getYearMonthDay(d)
},
prevYear() {
let d = this.getDate(this.time.year,this.time.month,1)
d.setFullYear(d.getFullYear() - 1)
this.time = this.getYearMonthDay(d)
},
nextYear() {
let d = this.getDate(this.time.year,this.time.month,1)
d.setFullYear(d.getFullYear() + 1)
this.time = this.getYearMonthDay(d)
}
}
}
</script>
<style scoped lang="less">
.pannel {
width: 32 * 7px;
position: absolute;
background: #fff;
margin-top: 10px;
box-shadow: 2px 2px 2px pink, -2px -2px 2px pink;
.pannel-nav {
display: flex;
justify-content: space-around;
height: 30px;
user-select: none;
span {
cursor: pointer;
}
}
.pannel-content {
span {
display: inline-flex;
justify-content: center;
align-items: center;
width: 32px;
height: 32px;
font-weight: bold;
box-sizing: border-box;
}
.cell {
cursor: pointer;
}
.cell:hover {
border: 1px solid pink;
}
.notCurrerntMonth {
color: gray;
}
.today {
background: red;
color: white;
}
.select {
background: pink;
color: white;
}
}
.pannel-footer {
height: 30px;
text-align: center;
}
}
</style>