基于Vue3实现日历组件的示例代码

作者:飞仔FeiZai 时间:2024-05-29 22:25:16 

以下是一个基于 Vue 3 实现的简单日历组件的代码示例。这个日历组件包含了前一个月、当前月、下一个月的日期,并且可以支持选择日期、切换月份等功能。

<template>
 <div class="calendar">
   <div class="header">
     <button class="prev" @click="prevMonth">&lt;</button>
     <div class="title">{{ title }}</div>
     <button class="next" @click="nextMonth">&gt;</button>
   </div>
   <div class="weekdays">
     <div v-for="day in daysOfWeek" :key="day" class="day">{{ day }}</div>
   </div>
   <div class="days">
     <div
       v-for="day in days"
       :key="day.date"
       :class="{
         today: isToday(day),
         selected: isSelected(day),
         notCurrentMonth: isNotCurrentMonth(day),
       }"
       @click="select(day)"
     >
       {{ day.day }}
     </div>
   </div>
 </div>
</template>

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

export default {
   name: "FeiCalendar",
   props: {
     selectedDate: Date,
   },
   emits: ["update:selectedDate"],
   setup(props, { emit }) {
     const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
     const currentDate = ref(new Date());
     const selectedDate = ref(props.selectedDate || currentDate.value);

const daysOfWeek = computed(() => {
       return weekdays;
     });

const days = computed(() => {
       const year = currentDate.value.getFullYear();
       const month = currentDate.value.getMonth();
       const daysInMonth = new Date(year, month + 1, 0).getDate();
       const daysInLastMonth = new Date(year, month, 0).getDate();
       const firstDayOfMonth = new Date(year, month, 1).getDay();

const days = [];
       let day = 1;
       let lastMonthDay = daysInLastMonth - firstDayOfMonth + 1;
       let nextMonthDay = 1;

for (let i = 0; i < 6 * 7; i++) {
         if (i < firstDayOfMonth) {
           days.push({
             date: new Date(year, month - 1, lastMonthDay),
             day: lastMonthDay,
             isLastMonth: true,
             isNextMonth: false,
           });
           lastMonthDay++;
         } else if (i >= firstDayOfMonth + daysInMonth) {
           days.push({
             date: new Date(year, month + 1, nextMonthDay),
             day: nextMonthDay,
             isLastMonth: false,
             isNextMonth: true,
           });
           nextMonthDay++;
         } else {
           const date = new Date(year, month, day);
           days.push({ date, day, isLastMonth: false, isNextMonth: false });
           day++;
         }
       }

return days;
     });

const title = computed(
       () =>
         `${currentDate.value.toLocaleString("default", {
           month: "long",
         })} ${currentDate.value.getFullYear()}`
     );

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

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

const isToday = (day) => {
       const today = new Date();
       return day.date.toDateString() === today.toDateString();
     };

const isSelected = (day) => {
       return day.date.toDateString() === selectedDate.value.toDateString();
     };

const isNotCurrentMonth = (day) => {
       return day.isLastMonth || day.isNextMonth;
     };

const select = (day) => {
       selectedDate.value = day.date;
       emit("update:selectedDate", day.date);
     };

return {
       daysOfWeek,
       days,
       title,
       prevMonth,
       nextMonth,
       isToday,
       isSelected,
       isNotCurrentMonth,
       select,
     };
   },
 };
</script>

<style>
 .calendar {
   max-width: 500px;
   margin: 0 auto;
   font-family: Arial, sans-serif;
 }

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

.title {
   font-size: 18px;
   font-weight: bold;
 }

.weekdays {
   display: flex;
   justify-content: space-around;
   margin-bottom: 10px;
 }

.day {
   width: 30px;
   height: 30px;
   display: flex;
   justify-content: center;
   align-items: center;
   border-radius: 50%;
 }

.days {
   display: grid;
   grid-template-columns: repeat(7, 1fr);
   grid-gap: 10px;
 }

.today {
   background-color: lightblue;
 }

.selected {
   background-color: blue;
   color: white;
 }

.notCurrentMonth {
   color: #ccc;
 }
</style>

使用该组件时,可以将selectedDate属性绑定到一个父组件中的数据,这个数据将会存储选中的日期。例如:

<template>
 <div>
   <!-- 用法一 -->
   <FeiCalendar
     :selectedDate="selectedDate"
     @update:selectedDate="onSelectedDateUpdated"
   />
   <!-- 用法二 -->
   <!-- <FeiCalendar v-model:selectedDate="selectedDate" /> -->
   <p>Selected date: {{ selectedDate }}</p>
 </div>
</template>

<script>
 import FeiCalendar from "./FeiCalendar.vue";

export default {
   components: {
     FeiCalendar,
   },
   data() {
     return {
       selectedDate: new Date(),
     };
   },
   watch: {
     selectedDate(nv) {
       console.log("nv", nv);
     },
   },
   methods: {
     onSelectedDateUpdated(selectedDate) {
       this.selectedDate = selectedDate;
     },
   },
 };
</script>

这是一个简单的示例,可以根据自己的需求对代码进行修改和扩展。

来源:https://www.cnblogs.com/yuzhihui/p/17332364.html

标签:Vue3,日历
0
投稿

猜你喜欢

  • vue实现选择商品规格功能

    2024-05-13 09:37:55
  • php mysql PDO 查询操作的实例详解

    2023-11-14 18:32:28
  • Python 命令行非阻塞输入的小例子

    2023-12-09 19:48:29
  • tensorflow自定义激活函数实例

    2023-04-18 09:11:51
  • python如何获取apk的packagename和activity

    2023-07-11 20:50:19
  • python使用pymongo与MongoDB基本交互操作示例

    2023-11-27 03:33:19
  • python中使用docx模块处理word文档

    2023-04-07 18:50:44
  • opencv-python图像增强解读

    2022-10-10 04:29:16
  • CSS 超链接图标规范 V1.0

    2007-12-28 12:05:00
  • Matplotlib 折线图plot()所有用法详解

    2023-01-30 06:10:30
  • 生成Jupyter Lab快捷方式的小技巧

    2022-11-29 11:55:42
  • Python处理JSON时的值报错及编码报错的两则解决实录

    2023-11-10 07:12:07
  • Vue前端后端的交互方式 axios

    2024-05-21 10:28:58
  • 详解python的变量缓存机制

    2023-05-11 07:47:45
  • javascript实现编写网页版计算器

    2024-04-23 09:26:25
  • python写一个md5解密器示例

    2023-05-24 14:45:10
  • 腾讯网QQ首页诞生的艰辛历程

    2008-11-06 11:05:00
  • Anaconda下安装mysql-python的包实例

    2024-01-25 08:04:29
  • 基于Python闭包及其作用域详解

    2023-11-07 07:22:02
  • 基于Python把网站域名解析成ip地址

    2021-08-23 05:31:06
  • asp之家 网络编程 m.aspxhome.com