实现“周”日历左右切换效果

背景:

        做项目时希望用到可左右切换日期的日历组件用于查看某日的待办项,然度娘无果最后问题到我这边,秉着技术问题不是问题且问题到我为止的原则,封装出以下组件。

效果:

    

此组件主要显示星期及日期,可左右点击查看历史和未来日期

话不多说直接上代码:代码只放了黄框圈中区域

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">&lt;</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">&gt;</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>

最后:

如果觉得有用请点赞加关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值