返回

动态展示签到状态,Vue3实战之掘金签到日历优化

前端







**一、回顾签到日历封装** 

在上篇分享中,我们封装了一个简单的签到日历组件,实现了签到天数和当前矿石数的静态数据绑定,以及日历控件的展示。回顾一下代码:

```javascript
<template>
  <div class="calendar-container">
    <div class="calendar-header">
      <span class="calendar-title">签到日历</span>
      <span class="calendar-date">{{ currentDate }}</span>
    </div>
    <div class="calendar-body">
      <div class="calendar-week">
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
      </div>
      <div class="calendar-days">
        <span v-for="day in days" :class="day.className" @click="handleDayClick(day)">{{ day.day }}</span>
      </div>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const currentDate = ref(new Date().toLocaleDateString());
    const days = ref([
      { day: 1, className: '' },
      { day: 2, className: '' },
      // ... 省略其他天数
    ]);

    const handleDayClick = (day) => {
      // 处理点击日期事件
    };

    return {
      currentDate,
      days,
      handleDayClick,
    };
  },
};
</script>

<style>
.calendar-container {
  width: 300px;
  margin: 0 auto;
}

.calendar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  border-bottom: 1px solid #ccc;
}

.calendar-title {
  font-size: 20px;
}

.calendar-date {
  font-size: 14px;
  color: #999;
}

.calendar-body {
  padding: 10px;
}

.calendar-week {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.calendar-week span {
  width: 30px;
  height: 30px;
  line-height: 30px;
  text-align: center;
  border: 1px solid #ccc;
}

.calendar-days {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.calendar-days span {
  width: 30px;
  height: 30px;
  line-height: 30px;
  text-align: center;
  border: 1px solid #ccc;
  cursor: pointer;
}

.calendar-days span.active {
  background-color: #007bff;
  color: #fff;
}
</style>

二、实现签到状态动态绑定

现在,我们需要实现签到状态的动态绑定,让签到日历能够实时显示用户是否已经签到。我们首先需要在签到日历组件中增加一个新的属性,用来存储签到状态。然后,我们在签到日历组件中监听这个属性的变化,并在属性发生变化时更新日历控件的显示状态。

<template>
  <div class="calendar-container">
    <div class="calendar-header">
      <span class="calendar-title">签到日历</span>
      <span class="calendar-date">{{ currentDate }}</span>
    </div>
    <div class="calendar-body">
      <div class="calendar-week">
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
      </div>
      <div class="calendar-days">
        <span v-for="day in days" :class="day.className" @click="handleDayClick(day)">{{ day.day }}</span>
      </div>
    </div>
  </div>
</template>

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

export default {
  props: ['签到状态'],
  setup(props) {
    const currentDate = ref(new Date().toLocaleDateString());
    const days = ref([
      { day: 1, className: '' },
      { day: 2, className: '' },
      // ... 省略其他天数
    ]);

    const handleDayClick = (day) => {
      // 处理点击日期事件
    };

    watch(() => props.签到状态, (newValue, oldValue) => {
      // 监听签到状态变化,更新日历控件的显示状态
      if (newValue) {
        // 已签到,将当天日期标记为已签到状态
        days.value[currentDate.value - 1].className = 'active';
      } else {
        // 未签到,将当天日期标记为未签到状态
        days.value[currentDate.value - 1].className = '';
      }
    });

    return {
      currentDate,
      days,
      handleDayClick,
    };
  },
};
</script>

现在,我们可以在父组件中通过