今天給你們介紹一下,如何在vue中實現自定義日曆組件,功能相似FullCalendar插件,可是卻比較靈活。html
先給你們看一下組件的效果圖,以下所示:vue
能夠在天天的日期中添加相應的內容,內容能夠是本身定義的,樣式也能夠是本身定義的,還有就是添加了複選框的功能。例如我用日從來體現天天價格,以下圖所示:api
下面來具體介紹一下是怎麼實現這個過程的,此次重點講這個組件的實現過程,涉及其它的先暫時不講,有疑問的能夠找我私聊。ide
具體代碼以下所示:this
<template> <div> <div class="cf setcal"> <div class="fl setcal-a"> <el-button type="text" @click="setCalendar(false);getData();setCalendarDayClear()"><i class="el-icon-caret-left"></i>{{month == 1 ? 12 : month - 1}}{{$t('calendar.month')}} </el-button> </div> <div class="fl setcal-b">{{year}}{{$t('calendar.year')}}{{month}}{{$t('calendar.month')}} <template> <el-checkbox v-model="checkedAll" @change="checkAll"></el-checkbox> </template> </div> <div class="fr setcal-a"> <el-button type="text" @click="setCalendar(true);getData();setCalendarDayClear()">{{month == 12 ? 1 : month + 1}}{{$t('calendar.month')}}<i class="el-icon-caret-right"></i></el-button> </div> </div> <div class="tableHead cf"> <div class="fl" v-for="(item,index) in internationalWeeks" :key="item.id">{{item.zh}} <template> <el-checkbox v-model="item.checked" @change="checkWeekAll(item, index)"></el-checkbox> </template> </div> </div> <div v-if="loadInitCalendar"> <template> <el-table :data="calendarTable" border style="width: 100%" :show-header="false"> <el-table-column v-for="(item, index) in weeks" :key="item.id"> <template slot-scope="scope"> <div class="calendar-item" v-if="scope.row[item.en].data"> <div class="cf"> <div class="fl">{{scope.row[item.en].data}}</div> <div class="fr" v-if="checkTodayDateLater(year+'-'+month+'-'+scope.row[item.en].data)<=0"> <template> <el-checkbox v-model="scope.row[item.en].checked" @change="checkDay(index,scope.$index);setData(year, month, scope.row[item.en],item.en)"></el-checkbox> </template> </div> </div> <div class="calendar-item-invenroty" v-if="scope.row[item.en].info.show" :style="{color: checkTodayDateLater(year+'-'+month+'-'+scope.row[item.en].data)<=0 ? '#1D8CE0' : '#8492A6'}"> <p>{{$t('calendar.price')}}:{{scope.row[item.en].info.price}}</p> <p>{{$t('calendar.salePrice')}}:{{scope.row[item.en].info.salePrice}}</p> <p>{{$t('calendar.num')}}:{{scope.row[item.en].info.saleNum}}/{{scope.row[item.en].info.num}}</p> </div> <div class="calendar-item-invenroty" v-else style="opacity: 0"> <p>{{$t('calendar.price')}}:999</p> <p>{{$t('calendar.salePrice')}}:999</p> <p>{{$t('calendar.num')}}:0/0</p> </div> </div> </template> </el-table-column> </el-table> </template> </div> </div> </template> <script> import hotelProductPrice from '@/api/product/hotelProductPrice' import { parseTime } from '@/utils/index' function initCalendar(year, month) { var monthFirstDay = new Date(year, month - 1, 1) var firstDay = monthFirstDay.getDay() // 返回本月1號是星期幾 var monthLastDay = new Date(year, month, 0) var lastDay = monthLastDay.getDate()// 返回本月共有多少天,同時避免複雜的判斷潤年不潤年 var week = ['seven', 'one', 'two', 'three', 'four', 'five', 'six'] var weekIndex = 0 var dateList = [] var dateData = {} var dateDataTemp = {} for (var i = 1; i <= 42; i++) { weekIndex++ dateDataTemp = {} if (firstDay < i && i <= (lastDay + firstDay)) { const date = i - firstDay dateDataTemp.data = date// 幾號對應星期幾 o dateDataTemp.checked = false } else { dateDataTemp.data = false// 沒數據 } dateDataTemp.info = { show: false, price: '', salePrice: '', num: '', saleNum: '', id: '' } dateData[week[(weekIndex - 1) % 7]] = dateDataTemp if (i % 7 === 0) { // 新的一週 dateList.push(dateData) dateData = {} weekIndex = 0 } } let ifPop = true for (const key in dateList[5]) { // 日曆第六行有數據 if (dateList[5][key].data) { ifPop = false break } } ifPop ? dateList.pop() : '' return dateList } export default { props: ['productId', 'distributorMchId'], name: 'Calendar', data() { return { infoId: '', loadInitCalendar: false, calendarTable: [{ seven: { data: '', checked: false }, one: { data: '', checked: false }, two: { data: '', checked: false }, three: { data: '', checked: false }, four: { data: '', checked: false }, five: { data: '', checked: false }, six: { data: '', checked: false } }], year: 0, month: 0, checkedAll: false, checkedAllLen: 0, checkedAllNum: 0, weeks: [ { id: '7', en: 'seven', zh: '日', checked: false, checkedNum: 0, checkedLen: 0 }, { id: '1', en: 'one', zh: '一', checked: false, checkedNum: 0, checkedLen: 0 }, { id: '2', en: 'two', zh: '二', checked: false, checkedNum: 0, checkedLen: 0 }, { id: '3', en: 'three', zh: '三', checked: false, checkedNum: 0, checkedLen: 0 }, { id: '4', en: 'four', zh: '四', checked: false, checkedNum: 0, checkedLen: 0 }, { id: '5', en: 'five', zh: '五', checked: false, checkedNum: 0, checkedLen: 0 }, { id: '6', en: 'six', zh: '六', checked: false, checkedNum: 0, checkedLen: 0 } ] } }, computed: { internationalWeeks() { return [ { id: '7', en: 'seven', zh: this.$t('calendar.sunday'), checked: false, checkedNum: 0, checkedLen: 0 }, { id: '1', en: 'one', zh: this.$t('calendar.monday'), checked: false, checkedNum: 0, checkedLen: 0 }, { id: '2', en: 'two', zh: this.$t('calendar.tuesday'), checked: false, checkedNum: 0, checkedLen: 0 }, { id: '3', en: 'three', zh: this.$t('calendar.wednesday'), checked: false, checkedNum: 0, checkedLen: 0 }, { id: '4', en: 'four', zh: this.$t('calendar.thursday'), checked: false, checkedNum: 0, checkedLen: 0 }, { id: '5', en: 'five', zh: this.$t('calendar.friday'), checked: false, checkedNum: 0, checkedLen: 0 }, { id: '6', en: 'six', zh: this.$t('calendar.saturday'), checked: false, checkedNum: 0, checkedLen: 0 }] } }, methods: { checkTodayDateLater(sDate2) { // sDate1和sDate2是2006-12-18格式 var date = new Date() var sDate1 = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() var aDate, oDate1, oDate2, iDays aDate = sDate1.split('-') oDate1 = new Date(aDate[1] + '-' + aDate[2] + '-' + aDate[0])// 轉換爲12-18-2006格式 aDate = sDate2.split('-') oDate2 = new Date(aDate[1] + '-' + aDate[2] + '-' + aDate[0]) iDays = parseInt((oDate1 - oDate2) / 1000 / 60 / 60 / 24)// 把相差的毫秒數轉換爲天數 return iDays }, setCalendar(w) { if (w) { if (this.month === 12) { this.month = 1 this.year++ } else { this.month++ } } else { if (this.month === 1) { this.month = 12 this.year-- } else { this.month-- } } this.calendarTable = initCalendar(this.year, this.month) this.setCheckedLen() this.$emit('setCalendarDayClear') }, // 每一個複選框 checkDay(x, y) { const week = this.weeks[x] this.calendarTable[y][week.en].checked ? week.checkedNum++ : week.checkedNum-- this.calendarTable[y][week.en].checked ? this.checkedAllNum++ : this.checkedAllNum-- week.checked = week.checkedNum === week.checkedLen this.checkedAll = this.checkedAllNum === this.checkedAllLen }, // 全選 checkAll() { this.checkedAllNum = this.checkedAll ? this.checkedAllLen : 0 for (let j = 0; j < this.weeks.length; j++) { const week = this.weeks[j] week.checked = this.checkedAll week.checkedNum = week.checked ? week.checkedLen : 0 } for (let i = 0; i < this.calendarTable.length; i++) { const obj = this.calendarTable[i] for (const key in obj) { if (obj[key].data) { obj[key].checked = this.checkedAll } } } const _this = this this.calendarTable.forEach(function(value, index) { const week = ['seven', 'one', 'two', 'three', 'four', 'five', 'six'] week.forEach(item => { if (value[item].data) { if (_this.checkTodayDateLater(_this.year + '-' + _this.month + '-' + value[item].data) <= 0) { _this.setData(_this.year, _this.month, value[item], item) } } }) }) }, // 周x全選 checkWeekAll(item, index) { const week = this.weeks[index] week.checked ? this.checkedAllNum += (week.checkedLen - week.checkedNum) : this.checkedAllNum -= week.checkedLen week.checkedNum = week.checked ? week.checkedLen : 0 this.checkedAll = this.checkedAllNum === this.checkedAllLen for (let i = 0; i < this.calendarTable.length; i++) { this.calendarTable[i][week.en].checked = week.checked } const _this = this this.calendarTable.forEach(function(value, index) { if (_this.checkTodayDateLater(_this.year + '-' + _this.month + '-' + value[item.en].data) <= 0) { _this.setData(_this.year, _this.month, value[item.en], item.en) } }) }, // 周有多少個 用於全選 setCheckedLen() { const tempObj = { seven: { checkedLen: 0 }, one: { checkedLen: 0 }, two: { checkedLen: 0 }, three: { checkedLen: 0 }, four: { checkedLen: 0 }, five: { checkedLen: 0 }, six: { checkedLen: 0 } } const _this = this let checkedAllLen = 0 let flag = false for (let i = 0; i < this.calendarTable.length; i++) { const obj = this.calendarTable[i] for (const key in obj) { if (!flag) { if (_this.checkTodayDateLater(_this.year + '-' + _this.month + '-' + obj[key].data) <= 0) { flag = true } } if (obj[key].data && flag) { tempObj[key].checkedLen++ checkedAllLen++ } } } this.checkedAllLen = checkedAllLen this.checkedAllNum = 0 this.checkedAll = false for (let j = 0; j < this.weeks.length; j++) { const week = this.weeks[j] week.checkedLen = tempObj[this.weeks[j].en].checkedLen week.checked = false week.checkedNum = 0 } }, getData(infoid) { if (infoid) { this.infoId = infoid } const week = ['seven', 'one', 'two', 'three', 'four', 'five', 'six'] hotelProductPrice.list(this.productId, this.distributorMchId, this.year, this.month).then(res => { this.loadInitCalendar = true const result = res.data const _this = this if (result) { result.forEach(function(apiValue, apiIndex) { let priceDate = parseTime(apiValue.priceDate, '{y}-{m}-{d}') priceDate = Number(priceDate.split('-')[2]) _this.calendarTable.forEach(function(value, index) { week.forEach(item => { if (value[item].data && value[item].data === priceDate) { value[item].info = { show: true, id: apiValue.id, price: apiValue.priceCodex, salePrice: apiValue.salePriceCodex, num: apiValue.stock, saleNum: apiValue.saleNum } } }) }) }) } }) }, setData(year, month, obj, week) { this.$emit('setData', year, month, obj, week) }, setCalendarDayClear() { this.$emit('setCalendarDayClear') }, initData(year, month) { this.calendarTable = initCalendar(year, month) this.setCheckedLen() this.getData() } }, mounted() { var date = new Date()// 系統時間對象 this.year = date.getFullYear()// 完整的年份,千萬不要使用getYear,firfox不支持 this.month = date.getMonth() + 1// 注意獲取的月份比實現的小1 this.calendarTable = initCalendar(this.year, this.month) this.setCheckedLen() this.getData() } } </script> <style scoped> .setcal { line-height: 20px; border: 1px solid #D3DCE6; line-height: 50px; } .setcal-a { text-align: center; width: 20%; } .setcal-b { width: 60%; text-align: center; border-right: 1px solid #D3DCE6; border-left: 1px solid #D3DCE6; } .calendar-item { padding: 5px; } .calendar-item-invenroty { font-size: 12px; } .tableHead div { width: calc(100% / 7); text-align: center; line-height: 3; background: #eef1f6; font-weight: bold; } p { margin: 0; padding: 0; } </style>
具體代碼就是上面所示,該日曆組件還實現了中英文切換的功能。插件
由於時間倉促,因此不能一個個分析代碼和原理,只能先貼出具體的代碼code