因為項目需要用到日歷組件捂贿,沒有找到適用的組件捞附,只能無奈自己寫一個了巾乳,達到項目使用所需的功能,同時保留了較高的擴展性鸟召。
先貼上效果圖
具體day的點擊事件邏輯就不貼出來了胆绊,有需要的根據自己的項目需求加上click即可
代碼分享
-父組件代碼
有使用到 elementui 的 el-button el-date-picker,照抄的同學記得下載依賴
<template>
<div>
<div class="top clearfix">
<div class="top-left fl">
<div class="tlt clearfix">
<span class="title1 fl">我的課表</span>
<el-button class="fr ml10" type="primary">下載排課表</el-button>
<div class="block fr">
<el-date-picker
v-model="value"
type="month"
:clearable=false
format="yyyy年 MM月"
@change="changeDate()"
placeholder="查看月份">
</el-date-picker>
</div>
</div>
<Calendar :defaultMonth.sync='defaultMonth'></Calendar>
</div>
</div>
</div>
</template>
<script>
import Calendar from '@/components/Calendar'
export default {
components:{Calendar},
data() {
return {
value:'',
defaultMonth:''
}
},
methods: {
changeDate(){
this.defaultMonth = this.value
}
},
created(){
let time = new Date()
this.value = time
this.defaultMonth = time
}
}
</script>
<style lang="stylus" scoped>
.clearfix::before,
.clearfix::after {
content: '';
display: table;
clear: both;
}
.fl{
float:left;
}
.fr{
float:right;
}
.title1{
color: #333
font-size: 20px;
font-weight 900
}
.top-left
height 750px
width 70%
background-color #fff
padding:20px;
border-radius: 10px;
&>.tlt
line-height 40px;
padding-bottom:10px;
</style>
-子組件代碼
<template>
<!-- 日歷組件 -->
<div class="calendar-box">
<table class="calendar-table">
<thead>
<th class="fc-day-header">日</th>
<th class="fc-day-header">一</th>
<th class="fc-day-header">二</th>
<th class="fc-day-header">三</th>
<th class="fc-day-header">四</th>
<th class="fc-day-header">五</th>
<th class="fc-day-header">六</th>
</thead>
<tbody>
<tr>
<td
v-for="(item, index) in calendarData"
:key="index"
:style="{'height': height}"
@click="clickDay(item)">
<div class="includeContent"
:class="{
'include': item.include,
'active': defaultDate.indexOf(item.date)>-1
}"
>
<slot name="day" :row="item">
<div class="day">
<span class="d_one">{{ item.day2 }}</span>
<span class="d_two" v-if="defaultDate.indexOf(item.date)>-1">課</span>
<span class="d_three" v-if="defaultDate.indexOf(item.date)>-1" v-text="courseList[defaultDate.indexOf(item.date)]"></span>
</div>
</slot>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'calendarBox',
props: {
type: { // all 可選中顯示的所有日期 portion 只能選中當前月份的數據
type: String,
default: 'portion'
},
defaultMonth: { // 默認日期
type: Date,
default () {
let year = new Date().getFullYear() // 當月年份
let month = new Date().getMonth() + 1 // 當月月份
return new Date(year, month - 1, 1)
}
},
height: { //設置td高度
type: String,
default: '94px'
}
},
data () {
return {
calendarData: [],
activeData: null,
defaultDate:['2022-4-1','2022-4-7','2022-4-13','2022-4-18','2022-4-26','2022-4-28','2022-5-5','2022-5-15','2022-5-18','2022-5-20','2022-5-21','2022-5-30'],
courseList:['美術課','武器課','瑜伽課','音樂課','吃飯','睡覺','看電影','逛街','考試','答辯','畢業(yè)','結婚'],
// allDate:[ //這里是模擬數據欧募,一般是從后臺接口獲取而來压状,需要自己獲取的時候拆分成 defaultDate 和 courseList
// {date:'2022-4-1',course:'美術課'},
// {date:'2022-4-7',course:'武器課'},
// {date:'2022-4-13',course:'瑜伽課'},
// {date:'2022-4-18',course:'音樂課'},
// {date:'2022-4-26',course:'吃飯'},
// {date:'2022-4-28',course:'睡覺'},
// {date:'2022-5-5',course:'看電影'},
// {date:'2022-5-13',course:'逛街'},
// {date:'2022-5-14',course:'畢業(yè)'},
// {date:'2022-5-20',course:'答辯'},
// {date:'2022-5-25',course:'結婚'},
// ]
}
},
created () {
this.getCalendarDay()
},
methods: {
// 獲取日歷天數
getCalendarDay () {
let year = new Date(this.defaultMonth).getFullYear() // 當月年份
let month = new Date(this.defaultMonth).getMonth() + 1 // 當月月份
let days = new Date(year, month, 0).getDate() // 當月天數
let prevYear = month === 1 ? (year - 1) : year // 上一年年份
let prevMonth = month === 1 ? 12 : (month - 1) // 上月月份
let prevDays = new Date(prevYear, prevMonth, 0).getDate() // 上一月天數
let lastYear = month === 12 ? (year + 1) : year // 下一年年份
let lastMonth = month === 12 ? 1 : (month + 1) // 下月月份
// let lastDays = new Date(lastYear, lastMonth, 0).getDate() // 下一月天數
let prevMonthArr = [] // 上月數據
let nextMonthArr = [] // 下月數據
let currentMonthArr = [] // 當月數據
// 判斷當月1號是星期幾
let firstDay = new Date(year, month - 1, 1).getDay()
// 獲取顯示上月的數據
for (let i = 0; i < firstDay; i++) {
let day = prevDays - firstDay + (i + 1)
let day2 = day >= 10 ? day : ('0' + day)
let month2 = prevMonth >= 10 ? prevMonth : ('0' + prevMonth)
prevMonthArr.push({
year: prevYear,
month: prevMonth,
month2: month2,
day: day,
day2: day2,
date: `${prevYear}-${prevMonth}-${day}`,
date2: `${prevYear}-${month2}-${day2}`,
include: false
})
}
// 獲取顯示的下一月的數據
for (let i = 0; i < (42 - firstDay - days); i++) {
let day = i + 1
let day2 = day >= 10 ? day : ('0' + day)
let month2 = lastMonth >= 10 ? lastMonth : ('0' + lastMonth)
nextMonthArr.push({
year: lastYear,
month: lastMonth,
month2: month2,
day: day,
day2: day2,
date: `${lastYear}-${lastMonth}-${day}`,
date2: `${lastYear}-${month2}-${day2}`,
include: false
})
}
// 獲取當月顯示數據
for (let i = 1; i <= days; i++) {
let day2 = i >= 10 ? i : ('0' + i)
let month2 = month >= 10 ? month : ('0' + month)
currentMonthArr.push({
year: year,
month: month,
month2: month2,
day: i,
day2: day2,
date: `${year}-${month}-${i}`,
date2: `${year}-${month2}-${day2}`,
include: true
})
}
this.calendarData = [...prevMonthArr, ...currentMonthArr, ...nextMonthArr]
},
// 設置默認值
setDefaultValue (date) {
if (!date) {
this.activeData = null
return
}
let year = new Date(date).getFullYear() // 當月年份
let month = new Date(date).getMonth() + 1 // 當月月份
let month2 = month >= 10 ? month : ('0' + month)
let day = new Date(date).getDate()
let day2 = day >= 10 ? day : '0' + day
let row = {
year: year,
month: month,
month2: month2,
day: day,
day2: day2,
date: `${year}-${month}-${day}`,
date2: `${year}-${month2}-${day2}`,
include: true
}
this.clickDay(row)
},
clickDay (row) {
if (this.type === 'portion' && !row.include) {
this.$message.closeAll()
this.$message({
type: 'info',
message: '只能選擇當前月份的日期'
})
return
}
this.activeData = { ...row }
this.$emit('click', { ...row })
// console.log(this.activeData);
}
},
watch: {
defaultMonth(){
this.setDefaultValue()
this.getCalendarDay()
}
}
}
</script>
<style lang="stylus" scoped>
$blue = #0176F6
.calendar-box {
background-color #f6f6f6
padding 10px;
.calendar-table {
width: 100%;
border-radius: 4px;
display: block;
overflow: hidden;
thead,
tbody {
display: flex;
width: 100%;
}
tr {
width: 100%;
}
th {
height: 50px;
line-height: 50px;
text-align: center;
color: #3E597B;
box-sizing: border-box;
display: inline-block;
width: 14.28%;
}
td {
width: 14.28%;
display: inline-block;
position: relative;
font-size: 16px;
font-weight: 500;
box-sizing: border-box;
text-align: center;
cursor: pointer;
border: solid 2px transparent;
color: rgba(62, 89, 123, 0.3);
background-color: #f5f5f5;
padding: 5px;
&>.includeContent{
border: 1px solid #DDD;
height 80px;
&.include {
color: #3E597B;
background-color: #fff;
}
&.active {
border: 2px solid $blue;
background: #BCDCFF;
color: $blue;
}
&:hover{
border: 2px solid $blue;
}
}
.day {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
position: relative;
&>.d_one{
position: absolute
top 5px
left 5px
}
&>.d_two{
position: absolute
top 5px
right 5px
}
&>.d_three{
width 100%
position: absolute
top 40px
left 50%;
transform: translateX(-50%)
}
}
&:nth-child(1),
&:nth-child(7),
&:nth-child(8),
&:nth-child(14),
&:nth-child(15),
&:nth-child(21),
&:nth-child(22),
&:nth-child(28),
&:nth-child(29),
&:nth-child(35),
&:nth-child(36),
&:nth-child(42) {
background: #f6f6f6; //根據自己需要,設置td周末的背景顏色
}
}
tbody {
.clickDay {
border: solid 2px #00BBBB;
}
}
}
}
</style>
使用注意事項
1.<style lang="stylus" scoped>
這里我用的是stylu
2.子組件props中的 type 和 height 我在父組件中沒有傳槽片,使用的是子組件的默認值
3.data(){} 中 defaultDate何缓、courseList、allDate參數請根據項目實際獲取參數使用
結束 over