vue实现自定义日历

前言
业务需要,做一个日历效果,但是某些ui框架,在使用过程中满足不了需求,所以只能自己造轮子了,于是有了这个东西,所以就自己写了这么一个东西,记录一下。

一、效果图

在这里插入图片描述

二、逻辑梳理

在这里插入图片描述

仿照百度搜索出来的日历,可以发现不仅有指定当前月份的号数而且可能还有上一个/下一个月的号数,但是总的来说一共展示出来的数据有7 * 6 = 42(天),所以我们需要先得到指定月份要展示的这42天是哪些日期号数,然后调整好页面布局依次循环展示这42天便可。

三、代码实现

定义一个方法获得42天是哪42天

	visibleCalendar() {
      // 获取今天的日期并将时间设置到 0分0秒0点
      const today = new Date()
      today.setHours(0)
      today.setMinutes(0)
      today.setSeconds(0)
      today.setMilliseconds(0)

      const calendarArr = []
      // 获取当前月份第一天
      const currentFirstDay = new Date(this.time.year, this.time.month, 1)
      // 获取第一天是周几,注意周日的时候getDay()返回的是0,要做特殊处理
      const weekDay =
        currentFirstDay.getDay() === 0 ? 7 : currentFirstDay.getDay()

      // 用当前月份第一天减去周几前面几天,就是看见的日历的第一天
      const startDay = currentFirstDay - (weekDay - 1) * 24 * 3600 * 1000
      // 我们统一用42天来显示当前显示日历
      for (let i = 0; i < 42; i++) {
        const date = new Date(startDay + i * 24 * 3600 * 1000)
        calendarArr.push({
          date: new Date(startDay + i * 24 * 3600 * 1000),
          year: date.getFullYear(),
          month: date.getMonth(),
          day: date.getDate(),
          // 是否在当月
          thisMonth:
            date.getFullYear() === today.getFullYear() &&
            date.getMonth() === today.getMonth()
              ? 'thisMonth'
              : '',
          // 是否是今天
          isToday:
            date.getFullYear() === today.getFullYear() &&
            date.getMonth() === today.getMonth() &&
            date.getDate() === today.getDate()
              ? 'isToday'
              : 'notToday',
          // 是否在今天之后
          afterToday: date.getTime() >= today.getTime() ? 'afterToday' : '',
          // 得到日期字符串
          timeStr: date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' 00:00:00',
          // 得到date类型日期
          timeDate: date
        })
      }
      return calendarArr
    }

上面代码中time的定义
time对象指的是要查询的年份月份。

time: {
  year: new Date().getFullYear(),
  month: new Date().getMonth()
}

下面的内容是重点

前端代码核心讲解(上面的看不明白没关系,下面手把手教你去实现一个日历功能)

核心在于 v-for=“(ite, idx) in visibleCalendar”, 这个visibleCalendar 是上面最开始定义的获取42天的方法,我们只需要循环遍历这个方法的返回结果就行了。因为visibleCalendar 这个function中定义了day属性,所以循环时只需要 ite.day就能拿到这一天的号数。至于效果图中的星期一到星期天与下面的日期号数对齐排列是怎么实现的呢?下面是代码开撸(把代码cv到自己页面合适的位置上能直接用):

日历星期几的展示,如下:

// vue页面中data中定义
top: ['一', '二', '三', '四', '五', '六', '日']

// vue页面使用
<div class="calendar-box">
	<!-- 日历表头 -->
	<div class="calendarTop">
		<div class="calendar-tag" v-for="ite in top" :key="ite">
			<span>{{ `星期` + ite }}</span>
		</div>
	</div>
	<!-- 具体内容 -->
	<div class="calendarBottom">...</div>
</div>


// vue style中的样式
.calendar-box {
	width: 100%; // 这里日历总的大小 取决于你自己的页面布局
	height: 100%;
	display: flex; // flex流式布局
	flex-direction: column; // flex流式布局 竖向排列
}
.calendarTop {
	width: 100%;
	height: 30px; // 根据自己的页面固定好高度
	display: flex; // flex流式布局 默认是横向排列
	justify-content: space-evenly; // flex流式布局 相等间距
}
.calendar-tag {
	width: 14%;
	height: 30px; // 高度根据自己页面调整 
}
.calendar-tag span {
	background-color: rgb(205, 237, 248); // 蓝底
    width: 100%; 
    height: 30px; // 高度根据自己页面调整 
    font-weight: bold; // 字体加粗
}
.calendarBottom {
	width: 100%;
	height: calc(100% - 30px); // 高度是父级div 的高度减去.calendarTop 的高度
}

效果如下:
在这里插入图片描述

然后是具体的内容对应,如下:

// vue computed中需要定义的方法
computed: {
    visibleCalendar() {
      // 获取今天的日期并将时间设置到 0分0秒0点
      const today = new Date()
      today.setHours(0)
      today.setMinutes(0)
      today.setSeconds(0)
      today.setMilliseconds(0)

      const calendarArr = []
      // 获取当前月份第一天
      const currentFirstDay = new Date(this.time.year, this.time.month, 1)
      // 获取第一天是周几,注意周日的时候getDay()返回的是0,要做特殊处理
      const weekDay =
        currentFirstDay.getDay() === 0 ? 7 : currentFirstDay.getDay()

      // 用当前月份第一天减去周几前面几天,就是看见的日历的第一天
      const startDay = currentFirstDay - (weekDay - 1) * 24 * 3600 * 1000
      // 我们统一用42天来显示当前显示日历
      for (let i = 0; i < 42; i++) {
        const date = new Date(startDay + i * 24 * 3600 * 1000)
        calendarArr.push({
          date: new Date(startDay + i * 24 * 3600 * 1000),
          year: date.getFullYear(),
          month: date.getMonth(),
          day: date.getDate(),
          // 是否在当月
          thisMonth:
            date.getFullYear() === today.getFullYear() &&
            date.getMonth() === today.getMonth()
              ? 'thisMonth'
              : '',
          // 是否是今天
          isToday:
            date.getFullYear() === today.getFullYear() &&
            date.getMonth() === today.getMonth() &&
            date.getDate() === today.getDate()
              ? 'isToday'
              : 'notToday',
          // 是否在今天之后
          afterToday: date.getTime() >= today.getTime() ? 'afterToday' : '',
          // 得到日期字符串,格式 yyyy-MM-dd 00:00:00
          timeStr: date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' 00:00:00',
          // 得到date类型日期
          timeDate: date
        })
      }
      return calendarArr
    }
}

// vue页面使用
<div class="calendar-box">
	<!-- 日历表头 -->
	<div class="calendarTop">
		<div class="calendar-tag" v-for="ite in top" :key="ite">
			<span>{{ `星期` + ite }}</span>
		</div>
	</div>
	<!-- 具体内容 -->
	<div class="calendarBottom">
		<div class="calendar-content">
			<div 
				class="calendar-item" 
				:class="ite.isToday" 
				v-for="(ite, indx) in visibleCalendar" 
				:key="indx">
				<!-- 号数 -->
				<div class="calendar-item-number">{{ ite.day }}</div>
				<!-- 号数对应的需要展示的内容 -->
				<div class="calendar-item-content">....</div>
			</div>
		</div>
	</div>
</div>

// vue style样式
.calendar-content {
	width: 100%;
    height: 100%;
    display: flex;
    flex-wrap: wrap; // 超出宽度换行
    justify-content: space-evenly;
}   
.calendar-item {
	width: 14%; // 这个宽度需要和 .calendar-tag 的宽度保持一致(和星期几对应)
	height: 16%; // 高度根据实际需求调整
	display: flex; // flex流式布局
}
.calendar-item-number {
	width: 100%;
	height: 20px;
}
.calendar-item-content {
	width: 100%;
	height: calc(100% - 20px);
}
.isToday {
	border: 1px solid #50bfff;
}

效果如下
在这里插入图片描述

四、作者的废话

visibleCalendar 这个方法按理来说只要用户改变了月份,日历对应的内容就该变化,所以建议直接把visibleCalendar 这个方法定义到 vue的computed 函数中。

效果图中的日期选择框是用的Antd Design Vue 中的组件,这个主要是我用来改变time对象的值,所以什么时候改变time对象的值完全取决于你用什么东西让用户去选择日期。至于关于自定义日历的相关颜色和大小需要根据自己的情况调整。

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我很抱歉,但是我无法直接通过引用内容查看具体的图片和代码。然而,根据你提供的引用信息,我可以告诉你关于vue日历自定义组件的一些信息。 根据引用,这个组件目录可以提供给你一些关于vue日历自定义组件的相关代码和文件。 根据引用,这个vue日历组件支持农历和假期展示,并且可以自定义可选择的日期范围。 根据引用,在组件中使用这个vue日历组件,你需要在main.js中引入它。组件默认情况下会显示一个自定义的左侧icon。某一个日期可以出现选中状态,也可以使用圆点模式来表示选中状态。你可以通过传递一个包含active属性的数组对象来自定义某一天的数据。 总的来说,这个vue日历自定义组件提供了一些可定制化的功能,包括农历展示、假期展示以及可选择日期范围等。你可以根据你的需求在组件中进行相应的配置和使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [vue自定义日历组件](https://blog.csdn.net/weixin_38644883/article/details/88067612)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [vue日历组件,支持农历以及假期展示,可以自定义可选择日期范围](https://download.csdn.net/download/qq_29597215/86267518)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值