首页 > 其他分享 >Vue3 日历组件的实现

Vue3 日历组件的实现

时间:2023-04-20 18:12:01浏览次数:56  
标签:const 日历 value Date currentDate Vue3 组件 selectedDate day

Vue3 日历组件的实现

以下是一个基于 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>

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

标签:const,日历,value,Date,currentDate,Vue3,组件,selectedDate,day
From: https://www.cnblogs.com/yuzhihui/p/17332364.html

相关文章

  • SpringBoot应用集成微服务组件Nacos
    目录springboot与微服务组件nacosNacos服务快速启动STS4开发工具Maven环境配置STS4开发工具引入Maven配置MavenRepo配置阿里云镜像源Springboot集成nacos服务springboot项目构建springboot集成微服务nacosnacos版本问题nacos2.0.0版本兼容性说明nacos升级文档nacos版本与spring......
  • Vue3 watch 监听对象数组中对象的特定属性
    Vue3watch监听对象数组中对象的特定属性在Vue3中,可以使用watch函数来监听对象数组中对象的特定属性。可以通过在回调函数中遍历数组来检查对象的特定属性是否发生变化,并在变化发生时执行相应的操作。一、监听对象的特定属性例如,假设有一个名为items的对象数组,其中每个......
  • 关于项目组件打包时遇到 `Uncaught TypeError: Cannot read property 'toLowerCase' o
    在全局注册组件时采用遍历组件池的方法时 每个组件都应该具备name属性 否则会出现UncaughtTypeError:Cannotreadproperty'toLowerCase'ofundefined  ......
  • 使用Layui树形组件如何取值
    近期使用了Layui中的树形组件来权限,发现无法没有提供直接获取选中值的id或code方法。分享一下个人方法官方案例 可以使用tree.getChecked('demoId')获取选中的节点,选中节点是个JSON无法直接获取指定code或者id等信息,需要我们自己处理一下 本方法可以获取指定层级的id或......
  • Vue独立组件开发: prop event slot
    本文是介绍独立组件开发的系列文章的第一篇。Vuejs无疑是当下最火热的前端框架,而它最精髓的,正是它的组件与组件化。写一个Vue项目,就是在写一个个的组件,掌握了Vue组件的各种开发模式与技巧,再复杂的业务场景也可轻松拿捏。组件的分类Vue组件分成三类:页面组件由 vue-router 产......
  • Vue 独立组件开发:不一样的组件通信方式
    本文是介绍独立组件开发的系列文章的第二篇。组件的通信组件一般来说有以下几种关系:父子关系隔代关系兄弟关系组件间经常会通信,Vue内置的通信手段一般有两种:ref:给元素或组件注册引用信息;$parent / $children:访问父/子实例。这两种方式都是直接得到组件的实例,然后直接调用组件......
  • 无界微前端(wujie):element-ui 弹框内使用select组件,弹出框位置异常解决方案 (主程序加载
    https://wujie-micro.github.io/doc/guide/ element-ui弹框内使用select组件,弹出框位置异常解决方案第一步:在子应用中: 以上3步就好啦!!!是不是很简单这个框架坑很多,希望对大家有帮助!!! ......
  • Vue3+TS+Node打造个人博客(后端架构)
    在使用Express搭建后端服务时,主要关注的几个点是:路由中间件和控制器SQL处理响应返回体数据结构错误码Web安全环境变量/配置路由和控制器路由基本上是按模块或功能去划分的。首先是按模块去划分一级路由,各个模块的子功能相当于是用二级路由处理。简单举个例子,/article......
  • vue全家桶进阶之路43:Vue3 Element Plus el-form表单组件
    在ElementPlus中,el-form是一个表单组件,用于创建表单以便用户填写和提交数据。它提供了许多内置的验证规则和验证方法,使表单验证更加容易。使用el-form组件,您可以将表单控件组织在一起,并对表单进行验证,以确保提交的数据符合预期的格式和要求。该组件具有以下特性:支持内置......
  • Android UI组件
    1.TextView知识点:autoLink:文本自动识别为web超链接、email地址等——第五章AcitonBar用法:自定义ActionBar——第四章创建Acticity选项菜单:让返回键在ActionBar中显示后,重写onOptionsItemSelected——第四章创建,注册监听器,实现按钮功能——第四章布局:<?xmlversion="1.0......