前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用APICloud AVM框架封装app日历组件

使用APICloud AVM框架封装app日历组件

原创
作者头像
APICloud官方
发布2022-04-06 13:46:55
4940
发布2022-04-06 13:46:55
举报

​实现的日历效果图

话不多说,上代码!

代码语言:javascript
复制
<template>
    <view class="page">
		<safe-area></safe-area>
		<view class="calendar-wrapper">
			<view class="calendar-toolbar">
				<text class="prev" onclick="prevMonth">〈</text>
				<text class="current">{{ currentDateStr }}</text>
				<text class="next" onclick="nextMonth">〉</text>
			</view>
			<view class="calendar-week">
				<text class="week-item" v-for="item of weekList" :key="item">{{ item }}</text>
			</view>
			<view class="calendar-inner">
				<text class="calendar-item" v-for="(item, index) of calendarList" :key="index" :class="this.changestyle(item.disable,item.value)"
				onclick="selDate" :data-val="item.value" :data-status="item.disable" :data-num="item.date">{{ item.date }}</text>
			</view>
		</view>
    </view>
</template>
<script>
	export default {
		name: 'calendar',
		installed(){
			this.setCurrent();
			this.calendarCreator();
		},
		data() {
			return{
				current:{},	
				weekList:['周日','周一','周二','周三','周四','周五','周六'],
				shareDate: new Date(),
				calendarList: [],
				seldate:'点击选择日期',
				selweek:'待定',
			}
		},
		computed: {
			// 显示当前时间
			currentDateStr() {
				let { year, month } = this.current;
				return `${year}年${this.pad(month + 1)}月`;
			}
		},
		methods: {
			selDate (e){
				// console.log(JSON.stringify(e.currentTarget.dataset.val));
				let status = e.currentTarget.dataset.status;
				let num = e.currentTarget.dataset.num;
				if(status){
					this.data.seldate = e.currentTarget.dataset.val;
					this.getWeek();
					if(num>7){
						this.prevMonth();
					}
					else{
						this.nextMonth();
					}
				}
				else{
					this.data.seldate = e.currentTarget.dataset.val;
					this.getWeek();
					//重新加载一次日历 改变样式
					this.calendarCreator();
				}
				this.fire('clickDate', this.data.seldate);
			},
			changestyle(status,date){
				if(status){
					return 'calendar-item-disabled';
				}
				else{
					if(date == this.data.seldate){
						return 'calendar-item-checked';
					}
					else{
						return 'calendar-item';
					}
				}
			},
			// 判断当前月有多少天
			getDaysByMonth(year, month) {
				// console.log("本月多少天:"+new Date(year, month + 1, 0).getDate());
				return new Date(year, month + 1, 0).getDate();
			},
			getFirstDayByMonths(year, month) {
				// console.log("本月第一天周几:"+new Date(year, month, 1).getDay());
				return new Date(year, month, 1).getDay();
			},
			getLastDayByMonth(year, month) {
				// console.log("本月最后一天周几:"+new Date(year, month + 1, 0).getDay());
				return new Date(year, month + 1, 0).getDay();
			},
			// 对小于 10 的数字,前面补 0
			pad(str) {
				return str < 10 ? `0${str}` : str;
			},
			// 点击上一月
			prevMonth() {
				this.current.month--;
				// 因为 month的变化 会超出 0-11 的范围, 所以需要重新计算
				this.correctCurrent();
				// 生成新日期
				this.calendarCreator();
			},
			// 点击下一月
			nextMonth() {
				this.current.month++;
				// 因为 month的变化 会超出 0-11 的范围, 所以需要重新计算
				this.correctCurrent();
				// 生成新日期
				this.calendarCreator();
			},
			// 格式化时间,与主逻辑无关
			stringify(year, month, date) {
				let str = [year, this.pad(month + 1), this.pad(date)].join('-');
				return str;
			},
			// 设置或初始化 current
			setCurrent(d = new Date()) {
				let year = d.getFullYear();
				let month = d.getMonth();
				let date = d.getDate();
				this.current = {
						year,
						month,
						date
				}
			},
			// 修正 current
			correctCurrent() {
				let { year, month, date } = this.data.current;
 
				let maxDate = this.getDaysByMonth(year, month);
				// 预防其他月跳转到2月,2月最多只有29天,没有30-31
				date = Math.min(maxDate, date);
 
				let instance = new Date(year, month, date);
				this.setCurrent(instance);
			},
			// 生成日期
			calendarCreator() {
				// 一天有多少毫秒
				const oneDayMS = 24 * 60 * 60 * 1000;
 
				let list = [];
				let { year, month } = this.data.current;
 
				// 当前月份第一天是星期几, 0-6
				let firstDay = this.getFirstDayByMonths(year, month);
				// 填充多少天                         
				let prefixDaysLen = firstDay === 0 ? 7 : firstDay;
				// 毫秒数
				let begin = new Date(year, month, 1).getTime() - oneDayMS * prefixDaysLen;
 
				// 当前月份最后一天是星期几, 0-6
				let lastDay = this.getLastDayByMonth(year, month);
				// 填充多少天, 和星期的排放顺序有关
				let suffixDaysLen = lastDay === 0 ? 6 : 6 - lastDay;
				// 毫秒数
				let end = new Date(year, month + 1, 0).getTime() + oneDayMS * suffixDaysLen;
 
				while (begin <= end) {
						// 享元模式,避免重复 new Date
						this.data.shareDate.setTime(begin);
						let year = this.data.shareDate.getFullYear();
						let curMonth = this.data.shareDate.getMonth();
						let date = this.data.shareDate.getDate();
						list.push({
								year: year,
								month: curMonth,
								date: date,
								disable: curMonth !== month,
								value: this.stringify(year, curMonth, date)
						});
						begin += oneDayMS;
				}
				this.data.calendarList = list;			
				// console.log(JSON.stringify(this.data.calendarList));
			},
			//获取选中日期的周几
			getWeek(){
				let index =new Date(this.data.seldate).getDay();
				let weekArr = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五','星期六'];
				let week = weekArr[index];
				this.data.selweek = week;
			},
		}
	}
</script>
<style>
    .page {
        height: 100%;
    }
	.calendar-wrapper {
		margin: 10px 10px 0 10px;
		background-color:#3c40c6;
		border-top-left-radius: 10px;
		border-top-right-radius: 10px;
		max-height: 400px;
	}
 
	.calendar-toolbar {
		padding: 10px 10px;
		flex-flow: row nowrap;
		justify-content: space-between;
		align-items: center;		
		border-bottom: 1px solid #fff;
	}
	.prev{
		flex: 1;
		text-align: center;
		color: #fff;
	}
	.current {
		flex: 1;
		text-align: center;
		color: #fff;
	}
	.next{
		flex: 1;
		text-align: center;
		color: #fff;
	}
 
	.calendar-week {
		padding: 5px 10px;
		flex-flow: row nowrap;
		justify-content: space-around;
		align-items: center;
	}
	.week-item { 
		padding: 5px;
		font-weight: bolder;
		font-size: 12px;
		color: #fff;
	}
	.calendar-inner{
		padding: 10px 10px;
		flex-flow: row wrap;
		justify-content: space-around;
		align-items: center;
	}
	.calendar-item {
		width:14%;
		font-weight: bolder;
		text-align: center;
		font-size: 15px;
		color: #fff;
		padding: 5px;
		background-color: #3c40c6;
	}
	.calendar-item-disabled {
		width:14%;
		font-weight: bolder;
		text-align: center;
		font-size: 15px;
		color: #999;
	}
	.calendar-item-checked {
		width:14%;
		font-weight: bolder;
		text-align: center;
		font-size: 15px;
		color: #000000;
		background-color: #ffffff;
		border-radius: 5px;
	}
</style>

其他页面引用

代码语言:javascript
复制
<template>
    <view class="page">
		<calendar onclickDate="getSelDate"></calendar>
		<view>
			<text>当前日期是</text>
			<text>{today}</text>
		</view>
    </view>
</template>
<script>
	import '../../components/calendar.stml'  
	export default {
		name: 'test',
		apiready(){
			
		},
		data() {
			return{
				today:''
			}
		},
		methods: {
			getSelDate(e){
				console.log(JSON.stringify(e));
				this.data.today = e.detail;
				api.toast({
					msg:'当前选中日期是:'+e.detail
				})
			}
		}
	}
</script>
<style>
    .page {
        height: 100%;
    }
</style>

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档