自定义vue3.0日历组件

一、前言

别人的东西用起来总是那么的不顺手,UI库的日历组件竟然不返回星期几,完全无法忍受,于是自己动手写了一个日历组件。
自己写的东西,那就是想怎么搞就怎么搞,哈哈哈哈哈。

二、代码

我使用的navie的按钮和tailwind的css,替换起来很方便的。

<template>
  <div class="w-full p-2">
    <h1 class="w-full flex justify-between items-center my-2 px-3 h-10 ">
      <span class="text-2xl leading-10 font-semibold">{{ nian + " " + hanziyue + "月" }}</span>
      <n-button-group>
        <n-button @click="gaimonth(-1)" round>
          <span>{{"<"}}</span>
          <span>{{"<"}}</span>
          <span>上个月</span>
        </n-button>
        <n-button @click="gaimonth(1)" round>
          <span>下个月</span>
          <span>{{">"}}</span>
          <span>{{">"}}</span>
        </n-button>
      </n-button-group>
      <n-button @click="getnianyueri()" type="primary">回到今天</n-button>
    </h1>
    <div class="w-full flex flex-wrap justify-start items-start">
      <div class="w-1/7 min-w-32  h-32 border border-gray-300 cursor-pointer" v-for="item in daylist" :key="item.timestamp" :class="item.month!==yue?'text-gray-400':''" @click="clickevent(item)">
        <div class="w-full h-5 flex justify-between items-center p-1">
          <span>{{item.day}}</span>
          <span v-if="item.day===xianzaitime.ri && item.month===xianzaitime.yue && item.year===xianzaitime.nian" class="text-blue-600">今天</span>
          <span>{{item.zhou}}</span>
        </div>
        <slot :year="item.year" :month="item.month" :day="item.day" :week="item.week"></slot>
      </div>
    </div>
  </div>
</template>

<script setup>
import {computed, ref,defineEmits} from "vue";
import {useStore} from "vuex"
import {useRoute, useRouter} from "vue-router"
import numtozh from "../../util/numtozh";
import weektozh from "../../util/weektozh";
import {NButton,NButtonGroup} from "naive-ui"
const store = useStore()
const router = useRouter()
const route = useRoute()
const emit = defineEmits(["handleclick","changemonth"])
// 需要展示的所有日期列表
const daylist = ref([])
// 年月日数据暂存
const shijian = ref(null)
const nian = ref(null)
const yue = ref(null)
const ri = ref(null)
const getnianyueri = (canshu = null) => {
  // 置空日期列表
  daylist.value = []
  if (canshu) {
    shijian.value = new Date(canshu)
  } else {
    shijian.value = new Date();
  }
  nian.value = shijian.value.getFullYear()
  yue.value = shijian.value.getMonth() + 1
  ri.value = shijian.value.getDate()
  // 当前显示月份改变后,需要向父组件抛出,父组件可以根据月份更新日程
  emit("changemonth",{year:nian.value,month:yue.value})
  tianchong()
}
// 计算需要展示的第一个日期
const startandendday=()=>{
  const cloneNowDate = new Date(shijian.value);
  // 先获取这个月的第一天
  const firstdaytime = cloneNowDate.setDate(1)
 // 获取第一天是周几  ,修改2021年7月26日 14:42:58,周日是0不是7,我草。
  let firstdayweek = new Date(firstdaytime).getDay()
  if(firstdayweek===0){
    firstdayweek=7
  }
  // 展示时间的第一天
  return firstdaytime - (firstdayweek - 1) * 24 * 60 * 60 * 1000
}
// 向列表填充数据
const tianchong=()=>{
  const starttime = startandendday()
  console.log(starttime,"开始时间")
  for (let i=0;i<=60;i++){
    let shuju = {}
    const shijianchuo = starttime + i*24*60*60*1000
    const sj = new Date(shijianchuo)
    const nian1 = sj.getFullYear()
    const yue1 = sj.getMonth() +1
    const ri1 = sj.getDate()
    const week = sj.getDay()
    if(yue.value===1){
      if(yue1>yue.value && yue1 !== 12){
        if(week===1 || week ===7){break}
      }
    }else if(yue.value===12){
      if(yue1-yue.value===-11){
        if(week===1 || week ===7){break}
      }
    }else{
      if(yue1>yue.value){
        if(week===1 || week ===7){break}
      }
    }
    shuju["timestamp"] = shijianchuo
    shuju["year"] = nian1
    shuju["month"] = yue1
    shuju["day"] = ri1
    shuju["week"] = week
    shuju["zhou"] = weektozh(week)
    daylist.value.push(shuju)
  }
}
// 日期点击事件
const clickevent=(item)=>{
  emit("handleclick",item)
  // 如果点击的日期不是当前月的,修改当前时间
  if(item.month !== yue.value){
    getnianyueri(item.timestamp)
  }
}
// 数字转汉字
const hanziyue = computed(()=>{
  return numtozh(yue.value)
})
// 点击上个月或者下个月
const gaimonth=(num)=>{
  let newmonth = yue.value + num
  // 如果大于12,转到下一年
  if(newmonth>12){
    nian.value += 1
    newmonth = 1
  }
  const sj = new Date(Date.parse(nian.value+"/"+newmonth+"/"+ri.value)).getTime()
  getnianyueri(sj)
}
// 获取今天的时间
const xianzaitime = ref({})
const getnow = ()=>{
  const sj = new Date()
  xianzaitime.value["nian"] = sj.getFullYear()
  xianzaitime.value["yue"] = sj.getMonth() +1
  xianzaitime.value["ri"] = sj.getDate()
}
// 初始化区域
getnow()
getnianyueri()
</script>

<style scoped>

</style>

引入的两个方法的代码

/*
* 数字转汉字,就是顶部显示的月份,数字不好看,换成汉字
* */
const dict = {
    0: "零",
    1: "壹",
    2: "贰",
    3: "弎",
    4: "肆",
    5: "伍",
    6: "陆",
    7: "柒",
    8: "捌",
    9: "玖",
    10: "拾",
    11: "拾壹",
    12: "拾贰",
}
export default function (num){
    return dict[num];
}
/*
* 数字转汉字,就是每个日期右上角显示的周几
* */
const dict2 = {
    1:"周一",
    2:"周二",
    3:"周三",
    4:"周四",
    5:"周五",
    6:"周六",
    0:"周日",
}
export default function (num){
    return dict2[num]
}

三、使用方法

<rili @handleclick="showtime" @changemonth=“getdata”>
      <template v-slot="yuansu">
        <div class="w-full h-full px-2 mt-1 overflow-x-hidden overflow-y-auto">
          <span>{{yuansu.year}}-{{yuansu.month}}-{{yuansu.day}}</span>
          <p>自定义内容</p>
        </div>
      </template>
    </rili>

四、效果图

在这里插入图片描述

五、结束

有问题或者意见可以提。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值