手写一个日历,记录签到-vue3

<template>
  <div class="calendar">
    <div class="header">
      <div class="header_left">
        <div class="totals">195</div>
        <div class="names">累计学习天数</div>
      </div>
      <div class="header_right">
        <div class="arrows" @click="prevMonth"><img src="../../../assets/Layout/home/icon_arrowleft.png" alt="" class="arrow_image"></div>
        <span class="same_month">{{ currentYear }}.{{ (currentMonth + 1).toString().padStart(2, '0') }}</span>
        <div class="arrows" @click="nextMonth"><img src="../../../assets/Layout/home/icon_arrowright.png" alt="" class="arrow_image"></div>
      </div>
    </div>
    <div class="weekdays">
      <div v-for="(day, index) in weekdays" :key="index" class="weekday">{{ day }}</div>
    </div>
    <div class="days">
      <div  v-for="(day, index) in days"  :key="index"  class="day"  :class="{ selected: isSelected(day) }"  @click="day && toggleDateSelection(day)">
        {{ day ? day.getDate() : '' }}
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

    const currentDate = ref(new Date());
    const selectedDates = ref(new Set());
    const weekdays = ['一', '二', '三', '四', '五', '六', '日'];
    const currentYear = computed(() => currentDate.value.getFullYear());
    const currentMonth = computed(() => currentDate.value.getMonth());

    const days = computed(() => {
      const firstDayOfMonth = new Date(currentYear.value, currentMonth.value, 1);
      const lastDayOfMonth = new Date(currentYear.value, currentMonth.value + 1, 0);
      const firstDayOfWeek = firstDayOfMonth.getDay();
      const daysInMonth = lastDayOfMonth.getDate();

      const calendarDays = [];
      for (let i = 0; i < firstDayOfWeek; i++) {
        calendarDays.push(null); // empty cells for previous month days
      }
      for (let day = 1; day <= daysInMonth; day++) {
        calendarDays.push(new Date(currentYear.value, currentMonth.value, day));
      }
      return calendarDays;
    });

    const toggleDateSelection = (day) => {
      if (!day) return;
      const dateString = day.toISOString().split('T')[0];
      if (selectedDates.value.has(dateString)) {
        selectedDates.value.delete(dateString);
      } else {
        selectedDates.value.add(dateString);
      }
    };

    const isSelected = (day) => {
      if (!day) return false;
      const dateString = day.toISOString().split('T')[0];
      return selectedDates.value.has(dateString);
    };

    const prevMonth = () => {
      currentDate.value = new Date(currentYear.value, currentMonth.value - 1, 1);
    };

    const nextMonth = () => {
      currentDate.value = new Date(currentYear.value, currentMonth.value + 1, 1);
    };

</script>

<style lang="scss" scoped>
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 30px;
  .header_left{
    .totals{
    font-family: Oswald;
    font-weight: 700;
    font-size: 40px;
    background: linear-gradient(to bottom, #E87421 , #FBCE89 );
    background-clip: text;
    -webkit-background-clip: text;
    color: transparent;
    }
    .names{
      font-weight: 400;
      font-size: 14px;
      color: rgb(0, 0, 0,.7);
    }
  }
  .header_right{
    display: flex;
    align-items: center;
    .arrow_image{
      width: 17px;
      height: 12px;
    }
    .same_month{
      margin: 0 15px;
      font-family: Oswald;
      font-weight: 700;
      font-size: 16px;
      color: rgb(0, 0, 0,.7);
    }
    .arrows{
      cursor: pointer;
    }
  }
}
.weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
  font-weight: bold;
  text-align: center;
  margin-bottom: 10px;
  font-size: 12px;
}
.days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);

}

.day {
  padding:10px;
  box-sizing: border-box;
  text-align: center;
  cursor: pointer;
  font-weight: bold;
  font-size: 12px;
  margin: 8px;
}

.day.selected {
  background: linear-gradient(-90deg, #27C5D4, #69EAF6);
  box-shadow: 0px 0px 8px 0px rgba(36,196,211,0.35);
  border-radius: 22px;
  color: #fff;
}
</style>

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3 打卡日历一个基于 Vue3 开发的日历组件,可以方便地展示月视图和周视图,并支持日历签到功能。 首先,在你的 Vue3 项目中安装 `vue3-calendar`: ``` npm i vue3-calendar ``` 然后在需要使用日历组件的地方引入: ```html <template> <div> <Calendar :events="events" :signed="signed" @event-click="onEventClick" @date-click="onDateClick" /> </div> </template> <script> import Calendar from 'vue3-calendar' export default { components: { Calendar }, data () { return { events: [ { title: 'Event 1', date: '2022-01-01' }, { title: 'Event 2', date: '2022-01-15' }, { title: 'Event 3', date: '2022-01-20' } ], signed: ['2022-01-01', '2022-01-15'] } }, methods: { onEventClick (event) { console.log(event) }, onDateClick (date) { console.log(date) } } } </script> ``` 在上面的代码中,我们将 `vue3-calendar` 引入并注册为 `Calendar` 组件。然后在模板中使用 `<Calendar>` 标签,并传入两个属性: - `events`:用于指定日历上显示的事件列表,每个事件包含 `title` 和 `date` 两个属性; - `signed`:用于指定哪些日期已经签到。 `<Calendar>` 组件还提供了两个事件: - `event-click`:当用户点击某个事件时触发,可以通过 `$event` 参数获取被点击的事件信息; - `date-click`:当用户点击某个日期时触发,可以通过 `$event` 参数获取被点击的日期信息。 最后,你需要在样式中引入日历组件的 CSS 文件: ```html <style> @import 'vue3-calendar/dist/vue3-calendar.css'; </style> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值