由于项目的需要,用到了日历组件,在北京时区下一切都很正常,直到切换时区后(下图案例为UTC-12:00),这个组件就出现了一些问题
该问题的原因:new Date() 会获取根据你电脑设置的时区来获取相应的时间
由于项目需要的解决方式为:将此组件设置为以北京时区为准。
但是我在网上搜索了一堆相关的解决方式,都不能够解决我的问题,所以我自己进行了一些细微的更改(如果你有更好的方式,欢迎指导)虽然这种方式很笨,但是有效
解决方式:
注意:千万不要使用 v-model 来绑定变量,否则就会出现上图的问题
<el-calendar class="calendar" ref="calendar">
<template slot="dateCell" slot-scope="{ date, data }">
<div :class="{'now-date':nowBJDate===data.day}" :id="data.day">
{{ data.day.split("-").slice(2).join("-") }}
</div>
</template>
</el-calendar>
首先介绍一下 slot-scope 中的两个字段里的值:
- date:根据你的时区获取到的日期,如果系统的时区与你想要的时区不同,就不要用这个date了
- data:{ type, isSelected, day},
type
表示该日期的所属月份,可选值有 prev-month,current-month,next-month;isSelected
标明该日期是否被选中;day
是格式化的日期,格式为 yyyy-MM-dd
第一步:使用 id 绑定上当前日期的字符串,主要用于快捷切换月份按钮(上个月-今天-下个月)使用
并给日期的这个div绑定上点击事件(因为没有v-model)所以需要以这种方式来监听选中日期
第二步:data中定义一个变量:nowBJDate;
在created中获取到当前的北京时间:new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })
将这个北京时间格式化为:yyyy-MM-dd 后赋值给 nowBJDate
created(){
// 是将传入日期格式化为指定格式的方法
this.nowBJDate = formatTime(new Date().toLocaleString('en-US', { timeZone: 'Asia/Shanghai' }),'Y-M-D')
this.changeNowBJDateFn() //调用定期刷新当前北京时间的方法
},
beforeDestroy(){
clearTimeout(this.changeBJDateTimer)
},
methods: {
changeNowBJDateFn(){
let bjDate1 = formatTime(new Date().toLocaleString('en-US', { timeZone: 'Asia/Shanghai' }),'Y-M-D h:m:s')
let bjDate2 = formatTime(new Date().toLocaleString('en-US', { timeZone: 'Asia/Shanghai' }),'Y-M-D 00:00:00')
let Countdown = +new Date(bjDate2) - +new Date(bjDate1) + 86401000 //获取当前北京时间到第二天00:00:01的时间差
this.changeBJDateTimer = setTimeout(()=>{
this.nowBJDate = formatTime(new Date().toLocaleString('en-US', { timeZone: 'Asia/Shanghai' }),'Y-M-D')
this.changeNowBJDateFn()
},Countdown)
},
}
第三步:在mounted生命周期中给快捷切换月份的按钮绑定点击事件,代码如下
let calendarEl = document.getElementsByClassName('el-calendar')[0];
let tdElArr = Array.from(calendarEl.getElementsByTagName('td'));//获取所有日期元素
tdElArr.forEach(item=>{
item.onclick = ()=>{
// 添加点击事件 item.children[0].children[0].id 指向 元素中的日期id
this.changeDate(item.children[0].children[0].id)
}
})
let btnBoxEl = document.getElementsByClassName('el-calendar__button-group')[0];
let btnEl = Array.from(btnBoxEl.getElementsByClassName('el-button'));//获取到三个按钮组成的数组
btnEl.forEach((item,index)=>{
// 遍历给每个按钮添加点击事件
item.onclick = (e)=>{
if(index==1){//index==1 的是回到今天,点击后直接调用pickDay方法指向当前北京时间
this.$refs.calendar.pickDay(this.nowBJDate);//调用日历插件中的选中日期方法
}
this.$nextTick(()=>{
// 这一步是获取此时被选中的日期的id,也就是格式化后的日期
let selectEl = calendarEl.getElementsByClassName('is-selected')[1]
if(selectEl){
//调用改变日期后获取数据的接口
this.changeSelectDay(selectEl.id)
}
})
}
})
// 这一步是初始化时的数据
this.changeSelectDay(this.nowBJDate)
// 给当前北京日期增加选中效果
this.$refs.calendar.pickDay(this.nowBJDate)
第四步:css样式调整
// 将element默认选中的今日日期蓝色字体去除
/deep/.el-calendar-table td.is-today{
color: #333 !important;
}
.now-date{
// 此处添加你自己的今日日期样式即可
}