自定义vue日历组件
今天给大家介绍一下,如何在vue中实现自定义日历组件,功能类似FullCalendar插件,但是却比较灵活。先给大家看一下组件的效果图,如下所示:可以在每天的日期中添加相应的内容,内容可以是自己定义的,样式也可以是自己定义的,还有就是添加了复选框的功能。例如我用日历来体现每天价格,如下图所示:下面来具体介绍一下是怎么实现这个过程的,这次重点讲这个组件的实现过程,涉及其它的先暂时不讲,有疑问的可以找
·
今天给大家介绍一下,如何在vue中实现自定义日历组件,功能类似FullCalendar插件,但是却比较灵活。
先给大家看一下组件的效果图,如下所示:
可以在每天的日期中添加相应的内容,内容可以是自己定义的,样式也可以是自己定义的,还有就是添加了复选框的功能。例如我用日历来体现每天价格,如下图所示:
下面来具体介绍一下是怎么实现这个过程的,这次重点讲这个组件的实现过程,涉及其它的先暂时不讲,有疑问的可以找我私聊。
具体代码如下所示:
<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>
具体代码就是上面所示,该日历组件还实现了中英文切换的功能。
因为时间仓促,所以不能一个个分析代码和原理,只能先贴出具体的代码,如果大家想要进一步的使用或者修改这个日历组件的话,可以添加我订阅号,我会在上面更新这个组件的其它用法,也可以直接加我微信私聊:lzqcode
如果大家觉得有必要做一个视频教程仔细的分析一下这个组件的实现原理,可以在订阅号中留言,如果需要的人数多的话,我会制作一个相关的教程出来的,然后将地址放在订阅号上面的。
更多推荐
已为社区贡献4条内容
所有评论(0)