完整代码参见github:vue-calendar-board
讲解组件封装之前,介绍时间对象Date相关的api:参见:MDN
实例:2019-03-03返回值是默认是日期的8:00:00,传入时间后按时间返回
2019,02,03返回日期是零点00:00:00,传入小时后按时间返回
//Sun Mar 03 2019 08:00:00 (中国标准时间)
const dt = new Date('2019-03-01')
// Sun Mar 03 2019 00:00:00 GMT+0800 (中国标准时间)
const st = new Date(dt.getFullYear(),dt.getMonth(),dt.getDate())
//Sun Mar 03 2019 02:00:00 GMT+0800 (中国标准时间)
const df = new Date('2019-03-03 2:00:00');
设置当前时间的日期,传0表示上个月的最后一天,传负数从上个月末开始算日期,传大于31的数字,表示下个月的日期
let today = new Date();
let last = new Date(today.getFullYear(), today.getMonth() + 1, 0);//获取当前月最后一天时间
let first = new Date(today.getFullYear(), today.getMonth(), 1)//获取当前月第一天
获取当前时间的日期
返回0,1,2,3,4,5,6对应数组:['周日', '周一','周二','周三','周四','周五','周六'],
1,根据日期获取日历行数(显示几个星期);
2,获取当月第一天是星期几,计算出日历第一行第一列显示上月的日期
3, 日历每天添加事件
4,日历组件添加默认事件和受控事件
1,仅显示格式需要:使用filter
2,需要复杂使用,可以重新再子组件内部定义一变量代替props,然后通过watch监听props的变量,更改时改变当前变量
使用$attrs和$listeners
calendar组件 header组件 body组件
<template>
<div class = "weeks-box">
<div class="weeks-title">
<strong class="week-day-title" v-for="(week,index) in weekTitles" :key="index">{{week}}</strong>
</div>
<div class="weeks-bg">
<div class="week-row" v-for = "(week, weekIndex) in currentDates" :key = "weekIndex">
<div
class="day-cell"
v-for = "(day, dayIndex) in week"
:key ="dayIndex"
@click = "onDayClick(day)"
>
<p :class="{ 'today':day.isToday }">{{day.monthDay}}</p>
<div class="event-box" v-show = " day.events.length > 0">
<div class="event-item" v-for = "(event,eventIndex) in day.events" :key = "eventIndex">
{{event.title}}
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { getStartDate, getDay } from './utils'
import config from './config'
export default {
props:{
currentDate:{
default(){
return new Date()
}
},
startDay:{
default:0
},
language:{
default:'zh'
},
events:{
default(){
return []
}
}
},
data(){
return {
weekTitles:[]
}
},
created(){
this.getWeekTitles();
},
beforeUpdate(){
},
upDate(){
},
computed:{
currentDateMock(){
const currentDate = [];
for(let i =0; i<5; i++){
currentDate[i] = [];
for(let k =0; k<7; k++){
currentDate[i].push({
monthDay:i.toString()+k,
event:[
{
title:'测试'
}
]
})
}
}
return currentDate;
},
currentDates() {
return this.getCalendar() //获取日历
}
},
watch:{
startDay(val){
const { weekNames } = config[this.language];
this.weekTitles = weekNames.slice(this.startDay).concat(weekNames.slice(0,this.startDay))
}
},
methods:{
getCalendar(){
const self = this;
let now = new Date();
//获取当前日期所在月份的第一天
let current = new Date(this.currentDate)
let startDate = getStartDate(current);
//获取当前日期的第一天的星期
let curWeek = getDay(startDate)
//根据开始日期是周几,第一列展示周几,计算出当前月份从哪一列开始展示 当月第一天向右偏移几天
let deviationNum = parseInt(this.startDay) - curWeek;
if(deviationNum>0){
deviationNum = deviationNum -7;
}
//设置第一行第一列的日期,循环时逐个增加一天
startDate.setDate(startDate.getDate() + deviationNum)
//计算出当前月份展示完成需要几个星期(几行)
let weeks = this.getWeeks(curWeek,current);
let calendar = [];
//给每一个星期(每一行添加数据)
for (let perWeek = 0; perWeek < weeks; perWeek++) {
calendar[perWeek] = [];
for(let i = 0;i<7;i++){
calendar[perWeek].push({
monthDay:startDate.getDate(),
isToday:now.toDateString() == startDate.toDateString(),
isCurMonth: startDate.getMonth() == current.getMonth(),
weekDay: i,
date:new Date(startDate),
events: self.filterEvents(startDate)
})
startDate.setDate(startDate.getDate()+1)
}
}
return calendar
},
//获取要展示的星期数,可能5行,也可能6行
getWeeks(curWeek,current){
//获取当前月份的天数(即获取本月的最后一天)
let curDayNum = new Date(current.getFullYear(),current.getMonth()+1,0).getDate()
let weeks;
//获取第一行展示当前月的天数 并计算显示几个星期(几行)
if(this.startDay == curWeek){
weeks = Math.ceil((31-7)/7)+1
}else if(this.startDay < curWeek){
weeks = Math.ceil((curWeek - this.startDay -7 + 31)/7)+1
}else{
weeks = Math.ceil((curWeek - this.startDay + 31)/7)+1
}
return weeks;
},
getWeekTitles(){
const { weekNames } = config[this.language];
this.weekTitles = weekNames.slice(this.startDay).concat(weekNames.slice(0,this.startDay))
},
filterEvents(date){
let thisDayEvents = this.events.filter(day => {
let dt = new Date(day.start)
let st = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate())
let ed = day.end ? new Date(day.end) : st
return date >= st && date <= ed
})
return thisDayEvents
},
onDayClick(day){
this.$listeners.onDayClick && this.$listeners.onDayClick()
}
}
}
</script>
完整代码参见github:vue-calendar-board
可以直接下载 npm install vue-calendar-board 使用