背景:
做项目时希望用到可左右切换日期的日历组件用于查看某日的待办项,然度娘无果最后问题到我这边,秉着技术问题不是问题且问题到我为止的原则,封装出以下组件。
效果:
此组件主要显示星期及日期,可左右点击查看历史和未来日期
话不多说直接上代码:代码只放了黄框圈中区域
HTML:
<template>
<div class="CalendarBox">
<div class="top">
<span>{{ DateConversion(selectedDate) }}</span>
<span @click="toToday">回到今日</span>
</div>
<div class="Calendar">
<div class="onLeft" @click="prevWeek"><</div>
<div class="center">
<div class="topDay">
<span v-for="(day, index) in daysOfWeek" :key="index">{{ day }}</span>
</div>
<div class="bottomDate">
<span
:class="{ 'current-month': isCurrentMonth(date), 'selected-date': isSelectedDate(date) }"
v-for="(date, index) in weekDates"
:key="index"
@click="onDateClick(date)"
>
{{ formatDay(date.getDate()) }}
</span>
</div>
</div>
<div class="onRight" @click="nextWeek">></div>
</div>
</div>
</template>
TS:
<script setup lang="ts">
import { computed, ref } from 'vue'
const currentDate = ref(new Date())
// 当前选中的日期
const selectedDate = ref<Date | null>(new Date())
const daysOfWeek = ['日', '一', '二', '三', '四', '五', '六']
// 设置对应日期
const getStartOfWeek = (date: Date): Date => {
const start = new Date(date)
const day = start.getDay()
const diff = start.getDate() - day
start.setDate(diff)
return start
}
// 日期变更函数
const getWeekDates = (date: Date): Date[] => {
const startOfWeek = getStartOfWeek(date)
const weekDates = []
for (let i = 0; i < 7; i++) {
const d = new Date(startOfWeek)
d.setDate(startOfWeek.getDate() + i)
weekDates.push(d)
}
return weekDates
}
// 计算属性监听日期变更函数触发日期更新
const weekDates = computed(() => getWeekDates(currentDate.value))
// 左箭头点击切换上一周的对应日期
const prevWeek = () => {
currentDate.value.setDate(currentDate.value.getDate() - 7)
currentDate.value = new Date(currentDate.value) // 强制触发更新
}
// 右箭头点击切换下一周的对应日期
const nextWeek = () => {
currentDate.value.setDate(currentDate.value.getDate() + 7)
currentDate.value = new Date(currentDate.value) // 强制触发更新
}
// 判断是否为本月日期设字体颜色
const isCurrentMonth = (date: Date): boolean => {
const today = new Date()
return date.getMonth() === today.getMonth() && date.getFullYear() === today.getFullYear()
}
// 判断是否为今天的日期或当前选中的日期设背景色
const isSelectedDate = (date: Date): boolean => {
return selectedDate.value?.getTime() === date.getTime()
}
// 10号前的日期补0
const formatDay = (day: number): string => {
return day < 10 ? `0${day}` : `${day}`
}
// 当前选中的日期
const DateConversion = (date: any) => {
// 获取年、月、日
let year = date.getFullYear()
let month = String(date.getMonth() + 1).padStart(2, '0') // 月份从0开始,因此加1
let day = String(date.getDate()).padStart(2, '0')
// 格式化为所需的字符串格式
return `${year}/${month}/${day}`
}
// 回到今天
const toToday = () => {
selectedDate.value = new Date()
currentDate.value = new Date(selectedDate.value)
}
// 日期点击事件
const onDateClick = (date: Date) => {
selectedDate.value = date
console.log(date)
}
</script>
CSS/LESS:
<style scoped lang="less">
.CalendarBox {
height: 110px;
padding: 0 10px;
border-bottom: 2px solid #ccc;
.top {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
span {
cursor: pointer;
}
}
.Calendar {
display: flex;
height: 60px;
justify-content: space-between;
align-items: center;
.onLeft {
cursor: pointer;
font-size: 24px;
}
.center {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
.topDay {
display: flex;
justify-content: space-around;
font-size: 18px;
color: #7f7f7f;
span {
cursor: default;
}
}
.bottomDate {
display: flex;
justify-content: space-around;
font-size: 16px;
span {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
width: 25px;
height: 25px;
border-radius: 10px;
overflow: hidden;
color: #a4a1a1;
}
.current-month {
color: #000;
}
.selected-date {
background-color: #a8c3f3;
}
}
}
.onRight {
font-size: 24px;
cursor: pointer;
}
}
}
</style>
最后:
如果觉得有用请点赞加关注!