上一版的日历组件是改的element-ui的,使用不方便,今天我也是闲了一会儿,就自己写了原生的,不依赖其他框架;其他个人定义组件
先看效果图:很简洁,后期可以加
组件API
width:组件宽度
makeArr:备注列表(传入一个数组:[{time:‘2020-02-28’,remark:‘28号测试备注’}])
dayChange:当前激活日期change事件
monthChange:月份变化change事件
calendar.vue
<template>
<!--
dayChange:当前激活日期change事件
monthChange:月份变化change事件
-->
<div class="lq-calendar" :style="'width:'+width">
<div class="calendar-header">
<div class="header-left">{{active.showText}}</div>
<div class="header-right">
<span class="btn" @click="setActiveMonth(1)">上个月</span>
<span class="btn" @click="setActiveMonth(2)">今天</span>
<span class="btn" @click="setActiveMonth(3)">下个月</span>
</div>
</div>
<div class="calendar-content">
<div class="calendar-week">
<span class="calendar-week-span" v-for="(item,index) in week" :key="index">{{item}}</span>
</div>
<div class="calendar-month">
<span
class="calendar-month-span"
@click="setDay(item)"
:class="checkState(item)"
v-for="(item,index) in month"
:key="index"
:ref="'day'+index"
>{{item.day}}</span>
</div>
<div class="calendar-remark">{{active.remark}}</div>
</div>
</div>
</template>
<script>
Date.prototype.format = function(fmt) {
var o = {
'M+': this.getMonth() + 1, //月份
'd+': this.getDate(), //日
'h+': this.getHours(), //小时
'm+': this.getMinutes(), //分
's+': this.getSeconds(), //秒
'q+': Math.floor((this.getMonth() + 3) / 3), //季度
S: this.getMilliseconds() //毫秒
}
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
(this.getFullYear() + '').substr(4 - RegExp.$1.length)
)
for (var k in o)
if (new RegExp('(' + k + ')').test(fmt))
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
)
return fmt
}
export default {
props: {
width: {
type: [String, Number],
default: '500px'
},
makeArr: {
type: Array,
default: () => {
return []
}
}
},
data() {
return {
today: '',
week: ['一', '二', '三', '四', '五', '六', '日'],
month: [],
activeMonth: {}, //当前选中的
active: {
remark: '',
showText: '' //当前月份
}
}
},
methods: {
//day单击事件
setDay(obj) {
if (obj.month == this.activeMonth.month) {
this.activeMonth = {}
this.active.remark = ''
this.checkState({})
} else {
this.active.remark = obj.remark
this.activeMonth = obj
this.checkState(obj)
}
this.$emit('dayChange',obj)
},
//备注匹配
checkMakeArr() {
let num = this.makeArr.length
for (let i = 0; i < num; i++) {
for (let j = 0; j < 42; j++) {
if (this.makeArr[i].time == this.month[j].month) {
this.month[j].remark = this.makeArr[i].remark
continue
}
}
}
},
//日历表格状态判定
checkState(val) {
let sty = []
if (!val.state) {
sty.push('calendar-month-state') //不属于本月css
}
if (val.month == this.today) {
sty.push('calendar-month-today') //今日css
}
if (val.remark != undefined) {
sty.push('calendar-month-remark') //有备注css
}
if (val.month == this.activeMonth.month) {
sty.push('calendar-month-click') //当前单击激活的css
}
return sty.join(' ')
},
//月份选择
setActiveMonth(val) {
let timeVal = this.active.showText
let prevmonth = new Date(new Date(timeVal).setDate(0)).format(
'yyyy-MM-dd'
)
let nextmonth = new Date(new Date(timeVal).setDate(32)).format(
'yyyy-MM-dd'
)
//val:1上个月,2今天,3下个月
switch (val) {
case 1:
this.getMonth(prevmonth)
break
case 2:
this.getMonth(this.today)
break
case 3:
this.getMonth(nextmonth)
break
}
this.$emit('monthChange',this.active.showText)
},
//星期判断
checkWeek(val) {
var date = new Date(val)
var day = date.getDay()
var wstr = '日一二三四五六'.charAt(day)
return { weekday: day, weekstr: wstr }
},
//今日日期
getTime() {
var today = new Date()
this.today = today.format('yyyy-MM-dd')
},
//日历矩阵处理
getMonth(val) {
this.month = []
var thismonth1 = new Date(new Date(val).setDate(1)).format('yyyy-MM')
this.active.showText = thismonth1
var thismonth2 = new Date(
new Date(new Date().setMonth(new Date(val).getMonth() + 1)).setDate(0)
).format('yyyy-MM-dd')
let num = parseInt(thismonth2.substr(8, 2))
for (let i = 1; i <= num; i++) {
let obj = {
month: '',
showText: thismonth1,
day: '',
state: true
}
if (i < 10) {
obj.month = thismonth1 + '-0' + i
obj.day = '0' + i
} else {
obj.month = thismonth1 + '-' + i
obj.day = i
}
obj = { ...obj, ...this.checkWeek(obj.month) }
this.month.push(obj)
}
this.setMonthBefore()
this.setMonthAfter()
this.checkMakeArr()
},
//日历矩阵处理 之前日期
setMonthBefore() {
let timeVal = this.month[0]
let num = timeVal.weekday == 0 ? 7 : timeVal.weekday
for (let i = 1; i < num; i++) {
let obj = {
month: '',
day: '',
state: false
}
obj.month = new Date(
new Date(timeVal.month).setDate(new Date(timeVal.month).getDate() - i)
).format('yyyy-MM-dd')
obj.showText = obj.month.substr(0, 7)
obj.day = obj.month.substr(8, 2)
obj = { ...obj, ...this.checkWeek(obj.month) }
this.month.unshift(obj)
}
},
//日历矩阵处理 之后日期
setMonthAfter() {
let timeVal = this.month[this.month.length - 1]
let num = 42 - this.month.length
for (let i = 1; i <= num; i++) {
let obj = {
month: '',
day: '',
state: false
}
obj.month = new Date(
new Date(
new Date().setMonth(new Date(timeVal.month).getMonth() + 1)
).setDate(i)
).format('yyyy-MM-dd')
obj.showText = obj.month.substr(0, 7)
obj.day = obj.month.substr(8, 2)
obj = { ...obj, ...this.checkWeek(obj.month) }
this.month.push(obj)
}
}
},
created() {
this.getTime()
this.getMonth(this.today)
}
}
</script>
<style lang='less' scoped>
.lq-calendar {
padding: 20px;
.calendar-header {
display: flex;
align-items: center;
padding: 0 calc(7.14% - 20px);
justify-content: space-between;
.btn {
cursor: pointer;
display: inline-block;
padding: 5px 10px;
text-align: center;
border: 1px solid #eae7e7;
outline: none;
}
.btn:hover {
background-color: #00cc8b;
color: #fff;
}
}
.calendar-content {
padding-top: 20px;
.calendar-week {
display: flex;
justify-content: center;
}
.calendar-week-span {
color: #666;
width: 20%;
display: inline-block;
text-align: center;
}
.calendar-month {
padding-top: 20px;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}
.calendar-month-span {
position: relative;
color: #333;
cursor: pointer;
width: 14.28%;
display: inline-block;
text-align: center;
height: 0;
padding-bottom: 7.14%;
line-height: 14.28%;
padding-top: 7.14%;
outline: #00cc8b;
}
.calendar-month-span:hover {
background-color: rgba(0, 204, 139, 0.5);
color: #fff;
}
.calendar-month-state {
color: #999;
}
.calendar-month-click {
background-color: rgba(0, 204, 139, 0.5);
color: #fff;
}
.calendar-month-today {
color: #fff;
background-color: #00cc8b;
}
.calendar-month-remark::after {
position: absolute;
content: '';
bottom: 3px;
left: 50%;
width: 6px;
height: 6px;
margin-left: -3px;
border-radius: 50%;
background-color: #00cc8b;
}
}
.calendar-remark {
padding: 0 5.14%;
}
}
</style>