手机端自定义日历组件(vue)

在这里插入图片描述

可复制查看效果、该代码为完整代码,同时,里面返回的字段可根据自己的业务需求进行更改. 关键字段:dataList是后台传过来需要显示在日历上的数据或任务,同时点击切换月份以及、对应的日期都能返回对应的月份以及当前点击的对象数据,方便进行数据请求等操作。ps:仅做记录,不喜勿喷(下次遇到同样需求,直接赋值黏贴,哈哈哈~)

一、HTML

<template>
	<view class="timepicker">
		<view class="current_data">直播日历:{{this.monthTitle}}</view>
		<view class="timepicker-box">
			<view class="box-section">
				<view class="section-slider">
					<view class="slider-year-month">
						<image src="/static/img/index/arrow_right.png" @click="getPreMonthDayList" class="pre"></image>
						<text class="year">{{this.monthTitle}}</text>
						<image src="/static/img/index/arrow_right.png" @click="getNextMonthDayList" class="next">
						</image>
					</view>
					<view class="slider-week">
						<text class="week-item" :key="key" v-for="(item, key) in weekText">{{item}}</text>
					</view>
					<view class="slider-day">
						<view :class="['day-item',item.isThisMonth?'':'not-current-month']" :key="key"
							v-for="(item, key) in days" @click="changeSelItem(item,key)">
							<view
								:class="['day',item.isToDay?'day-item-current':'', selIndex==key?'day-item-sel':'',item.propsAttr.length?'sel':'']">
								{{item.day}}
							</view>
						</view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

二、JS

<script>
	import {
		formatDate,
		returnData,
		getFirstAndLast,
		isToday
	} from '@/common/tools/day.js'

	export default {
		name: "timepicker",
		data() {
			return {
				weekText: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
				currentDay: '', //当前几号
				currentYear: '', //当前年
				currentMonth: '', // 当前月
				currentWeek: '', // 当前月1号是星期几? 0表示星期天
				monthTitle: '',
			    dataList: [{
				 	bgcolor: "#67b7f0",
				 	id: 1180,
				 	className: "二级建造师考试",
				 	data: "2022-06-26"
				 }], //有任务的日期
				thisMonthDay: [],
				days: [], //所有日期
				firstDay: new Date(),
				weekDay: new Date().getDay(), //获取今天是周几
				selIndex: -1,
			};
		},
		props: {
			//有任务的日期
			//dataList: {
			//	require: false,
			//	type: Array,
			//	default: () => []
			//}
		},
		computed: {},
		created() {
			this.firstDay.setDate(this.firstDay.getDate() - this.weekDay); //获取本周第一天的日期
			this.initData()
		},
		methods: {
			// 选中日期
			changeSelItem(item, index) {
				this.selIndex = index;
				this.$emit('clickCurrentDay', item)
			},
			// 下月
			getNextMonthDayList() {
				this.pickNext(this.currentYear, this.currentMonth);
			},
			// 上月
			getPreMonthDayList() {
				this.pickPre(this.currentYear, this.currentMonth);
			},
			// 上一月 (@param year, @param month)
			pickPre(year, month) {
				console.log("上一月")
				var d = new Date(formatDate(year, month, 1));
				d.setDate(0); //设置为上个月
				this.initData(formatDate(d.getFullYear(), d.getMonth() + 1, 1));
				this.$emit('currentYM', {
					year: this.currentYear,
					month: this.currentMonth
				})
			},
			// 下一个月 (@param year, @param month)
			pickNext(year, month) {
				console.log("下一个月")
				var d = new Date(formatDate(year, month, 1));
				d.setDate(35);
				this.initData(formatDate(d.getFullYear(), d.getMonth() + 1, 1));
				this.$emit('currentYM', {
					year: this.currentYear,
					month: this.currentMonth
				})
			},
			// 初始化月
			initData(cur) {
				var date;
				if (cur) {
					// 切换上一月、下一月
					date = new Date(cur);
				} else {
					var now = new Date(); // 此处取本机时间,应改为服务器时间
					// console.log(now.getFullYear(), now.getMonth() + 1, 1)
					var date = new Date(formatDate(now.getFullYear(), now.getMonth() + 1, 1));
				}

				this.currentDay = new Date().getDate(); // 今日日期 几号
				this.currentYear = date.getFullYear(); // 当前年份
				this.currentMonth = date.getMonth() + 1; // 当前月份
				this.currentWeek = date.getDay(); // 当前月1号是星期几? 0表示星期天
				// console.log(this.currentYear, this.currentMonth)
				var month = this.currentMonth >= 10 ? this.currentMonth : "0" + this.currentMonth;
				this.monthTitle = this.currentYear + "-" + month;
				// 当前月最后一天是星期几? 0表示星期天
				var nextWeek = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDay();
				var str = formatDate(this.currentYear, this.currentMonth, 1); // 2021/05/01
				var nextStr = new Date(
					date.getFullYear(),
					date.getMonth() + 1,
					0
				).toLocaleDateString(); // 2021/05/31
				var daysList = []; // 初始化日期
				// 设置上一个月 需显示 的最后几天  铺满一周
				for (var i = this.currentWeek; i > 0; i--) {
					var d = new Date(str);
					d.setDate(d.getDate() - i);
					var tod = returnData(d); //获取完整日期
					var dayobject = {
						d: tod,
						data: tod,
						day: d.getDate(),
						isThisMonth: d.getMonth() + 1 == this.currentMonth ? true : false,
						isToDay: isToday(tod),
						isSign: this.isVerDate(d),
						propsAttr: this.copyAttr(d, this.dataList),
					}; // 用一个对象包装Date对象  以便为以后预定功能添加属性
					daysList.push(dayobject); // 将日期放入data 中的days数组 供页面渲染使用
				}
				// 显示当前月的天数  第二个循环为 j<= 36- currentWeek,
				// 因为1号是星期六的时候当前月需显示6行,如2020年8月
				var num = 0; //第几个月 每遇到1号加1
				for (var j = 0; j <= 36 - this.currentWeek; j++) {
					var d = new Date(str);
					d.setDate(d.getDate() + j);
					var tod = returnData(d); //获取完整日期
					var dddd = d.getDate();
					var dayobject = {
						d: tod,
						data: tod,
						day: d.getDate(),
						isThisMonth: d.getMonth() + 1 == this.currentMonth ? true : false,
						isToDay: isToday(tod),
						isSign: this.isVerDate(d),
						propsAttr: this.copyAttr(d, this.dataList),
					};
					if (dddd == 1) {
						num++;
					}
					if (num == 2) {
						break;
					}
					daysList.push(dayobject);
				}
				// 设置下一个月 需显示 的最前几天铺满一周
				for (var k = 1; k <= 6 - nextWeek; k++) {
					var d = new Date(nextStr);
					d.setDate(d.getDate() + k);
					var tod = returnData(d); //获取完整日期
					var dayobject = {
						d: tod,
						data: tod,
						day: d.getDate(),
						isThisMonth: d.getMonth() + 1 == this.currentMonth ? true : false,
						isToDay: isToday(tod),
						isSign: this.isVerDate(d),
						propsAttr: this.copyAttr(d, this.dataList),
					}; // 用一个对象包装Date对象  以便为以后预定功能添加属性
					daysList.push(dayobject); // 将日期放入data 中的days数组 供页面渲染使用
				}
				// 设置本月的所有日期
				this.thisMonthDay = daysList.filter((item, index) => {
					if (isToday(item.d)) {
						this.selIndex = index;
					}
					return item.isThisMonth
				})
				this.days = daysList;
				// console.log(daysList)
			},
			// 判断该日期是否有任务
			isVerDate(d) {
				let dda = returnData(d);
				this.signdays = [];
				for (var i in this.sign_Month) {
					this.signdays.push(this.sign_Month[i].data);
				}
				return this.signdays.includes(dda);
			},
			// 复制元素的所有属性
			copyAttr(d, List, type) {
				// 日期   原数组
				var dd = null;
				if (type) {
					dd = d;
				} else {
					dd = returnData(d);
				}
				var ArrayList = [];
				if (List.length > 0) {
					List.forEach(item => {
						if (item.data == dd) {
							// item.tt = getHourAndMin(item.start) + '-' + getHourAndMin(item.end)
							ArrayList.push(item)
						}
					})
					return ArrayList
				} else {
					return []
				}
			},

		}
	};
</script>

day.js

// 返回 类似 2020/01/01 格式的字符串 ok
const formatDate = function(year, month, day) {
	month < 10 && (month = "0" + month);
	day < 10 && (day = "0" + day);
	return year + "-" + month + "-" + day;
};

//获取完整日期
const returnData = function(d) {
	var year = d.getFullYear();
	var month = d.getMonth() + 1;
	var day = d.getDate();
	var m = month >= 10 ? month : "0" + month;
	var daa = day >= 10 ? day : "0" + day;
	return year + "-" + m + "-" + daa;
};

// 获取本月第一天和最后一天
const getFirstAndLast = function(d, type = null) {
	var obj = {},
		arr = [],
		now,
		nowMonth,
		nowYear;
	if (d) {
		now = new Date(d); //当前日期
		nowMonth = now.getMonth(); //当前月
		nowYear = now.getFullYear(); //当前年
	} else {
		now = new Date(); //当前日期
		nowMonth = now.getMonth(); //当前月
		nowYear = now.getFullYear(); //当前年
	}
	//本月的开始时间
	var monthStartDate = new Date(nowYear, nowMonth, 1);
	var startY = monthStartDate.getFullYear();
	var startM = monthStartDate.getMonth() + 1;
	var startD = monthStartDate.getDate();
	var SAllTime = startY + "-" + startM + "-" + startD + " 00:00:00";
	if (type) {
		var firstTime = startY + "-" + startM + "-" + startD;
	}
	//本月的结束时间
	var monthEndDate = new Date(nowYear, nowMonth + 1, 0);
	var endY = monthEndDate.getFullYear();
	var endM = monthEndDate.getMonth() + 1;
	var endD = monthEndDate.getDate();
	var EAllTime = endY + "-" + endM + "-" + endD + " 23:59:59";
	if (type) {
		var EndTime = endY + "-" + endM + "-" + endD;
	}
	var dStart = new Date(SAllTime);
	var dEnd = new Date(EAllTime);
	// console.log(monthStartDate,monthEndDate)
	if (type) {
		arr = [{
				data: firstTime
			},
			{
				data: EndTime
			}
		];
	} else {
		obj = {
			start: dStart,
			end: dEnd
		};
	}

	var data1 = new Date(obj.start);
	var data2 = new Date(obj.end);
	if (type) {
		return arr;
	} else {
		return {
			startTime: data1.getTime() / 1000,
			endTime: data2.getTime() / 1000
		};
	}
};
// 判断是否为今天
const isToday = function(str) {
	var d = new Date();
	var y = d.getFullYear(); // 年
	var m = d.getMonth() + 1; // 月份从0开始的
	var d = d.getDate(); //日
	let ma = m >= 10 ? m : "0" + m;
	let da = d >= 10 ? d : "0" + d;
	return str == y + "-" + ma + "-" + da;
};
export {
	formatDate,
	returnData,
	getFirstAndLast,
	isToday
}

三、CSS

<style lang="scss" scoped>
	.timepicker {
		width: 100%;
		padding: 30rpx;
		box-sizing: border-box;

		.timepicker-box {
			display: flex;
			flex-direction: column;
			width: 100%;
			height: auto;
			background: #fff;

			.box-section {
				position: relative;
				flex: 1;

				.section-slider {
					display: flex;
					flex-direction: column;

					.slider-year-month {
						padding: 12rpx 10%;
						display: flex;
						align-items: center;
						justify-content: space-between;

						.pre {
							width: 40rpx;
							height: 40rpx;
							transform: rotate(180deg);
						}

						.next {
							width: 40rpx;
							height: 40rpx;
						}
					}

					.slider-week {
						display: flex;
						font-weight: bold;
						align-items: center;
						color: #333;

						.week-item {
							flex: 1;
							font-size: 32rpx;
							padding: 15rpx 0 20rpx;
							border-bottom: 1px solid #eee;
							text-align: center;
						}
					}

					.slider-day {
						padding: 10rpx 0;
						display: flex;
						flex-wrap: wrap;

						.day-item {
							display: flex;
							align-items: center;
							justify-content: center;
							color: #333;
							width: 14.28%;
							height: 80rpx;
							text-align: center;
							font-size: 28rpx;

							.day {
								width: 70rpx;
								line-height: 70rpx;
								height: 70rpx;
								border-radius: 50%;
								position: relative;
							}

							.sel:after {
								position: absolute;
								display: block;
								content: "";
								width: 6rpx;
								height: 6rpx;
								margin: auto;
								border-radius: 50%;
								background: #677FD2;
								left: 0;
								right: 0;
								bottom: 0;
							}
						}

						.day-item-current {
							color: red;
							background: #EAEAEA;
						}

						.day-item-sel {
							background: #677FD2;
							color: #fff;
						}


						.not-current-month {
							.day {
								color: #c9c6c6;
							}
						}
					}
				}
			}

			.box-footer {
				flex-basis: 10%;
				display: flex;
				box-shadow: 0px -1px 0px #eee;

				.footer-btn {
					flex: 1;
					text-align: center;

					span {
						font-size: 16px;
					}

					&:not(:last-child) {
						box-shadow: 1px 0px 0px #eee;
					}
				}
			}
		}
	}
</style>

4、最终效果

在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
我很抱歉,但是我无法直接通过引用内容查看具体的图片和代码。然而,根据你提供的引用信息,我可以告诉你关于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 ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值