vue/uni-app之空手撕日历

栏目: JavaScript · 发布时间: 5年前

内容简介:项目需要,没有合适的轮子,所以,,,效果(红圈部分):缩进变成4空格了。。。

项目需要,没有合适的轮子,所以,,,

效果(红圈部分):

vue/uni-app之空手撕日历

需求

  • 日期对应星期显示
  • 今天包括今天之前禁用
  • 某产品的最短预定时间内禁用,如提前三天,则今天明天后天禁用
  • 日期下面显示对应的价格
  • 简易版: 如果要当成完全的日历,还需完善

思路

  • 传入年份,月份创建日历;日期价格数组;日期禁用数组

  • 创建一个二维数组,第一维存放一月的周树,第二维存放一周的天数;一维的周树最多有七个数组

  • 每个日期包含年月日三个属性,价格对应的日期也是年月日,禁用的日期页按照年月日,所以匹配一下就可以了

  • 每月天数使用 js 原生判断,即:

    js 中 new Date('2019-06-21') 传入一个日期,可以用来判断某个月是否有某一天。

    没有的话,返回下一个月一号的构造函数;有的话返回这一天的构造函数;超出31号的则是Invalid

    vue/uni-app之空手撕日历
    // 验证日期是否有效:对应的月份是否有这一天
    validDate(year, month, date) {
    	let time = new Date(`${year}-${month}-${date}`);
    	let _year = time.getFullYear();
    	let _month = time.getMonth() + 1;
    	let _date = time.getDate();
    	
    	return _year === year && month === _month && date === _date
    }
    复制代码

    生成当月天数按周分割的数组

    // 生成一个月的天数
    generateCalendar(year, month) {
    	let that = this;
    	let weekLen = new Array(7).fill(''); // 一周七天
    	let weekday = new Date(`${year}-${month}-01`).getDay(); // 1号星期几
    	
    	// 重置
    	this.monthDay = [[], [], [], [], [], []];
    	
    	// 生成一月对齐星期的天数,一周以周日开始
    	weekLen.map((item, index) => {
    		that.monthDay[0].push(
    			index < weekday 
    			? '' 
    			: (index === weekday) 
    				? {year, month, date: 1}
    				: {year, month, date: that.monthDay[0][index-1].date+1}
    		);
    		that.monthDay[1].push({year, month, date: index + (7 - weekday + 1)});
    		that.monthDay[2].push({year, month, date: that.monthDay[1][index].date + 7});
    		that.monthDay[3].push({year, month, date: that.monthDay[2][index].date + 7});
    		if (
    			that.monthDay[3][index].date + 7 <= 31 && 
    			this.validDate(year, month, that.monthDay[3][index].date + 7)
    		) {
    			that.monthDay[4].push({year, month, date: that.monthDay[3][index].date + 7});
    		} else {
    			that.monthDay[4].push('');
    		}
    		if (
    			that.monthDay[4][index].date + 7 <= 31 && 
    			this.validDate(year, month, that.monthDay[4][index].date + 7)
    		) {
    			that.monthDay[5].push({year, month, date: that.monthDay[4][index].date + 7});
    		}
    	})
    }
    
    复制代码

代码

缩进变成4空格了。。。

父组件使用

<cus-calendar 
	class="calendar" 
	:year="monthActive.year" 
	:month="monthActive.month" 
	:saleList="saleList"
	:disabledDate="disabledDate"
	@check-date="checkDate" 
/>
复制代码

其他:

this.disabledDate = ['2019-06-21','2019-06-22','2019-06-23'];
this.saleList = [
	{ date: '2019-06-24', price: 6188 },
	{ date: '2019-06-25', price: 6188 },
	{ date: '2019-06-26', price: 6188 },
	{ date: '2019-07-26', price: 6188 },
	{ date: '2019-06-27', price: 6188 },
	{ date: '2019-06-28', price: 6188 },
];
复制代码

template

<template>
	<view class="calendar-container">
		<view class="month-bg">
			{{ month }}
		</view>
		<view class="week-title">
			<text class="weekend">日</text>
			<text>一</text>
			<text>二</text>
			<text>三</text>
			<text>四</text>
			<text>五</text>
			<text class="weekend">六</text>
		</view>
		
		<view class="calendar-content">
			<view 
				v-for="(week, weekindex) in monthDay"
				:key="weekindex"
				class="week-month"
			>
				<view
					class="date"
					v-for="(date, dateindex) in week"
					:key="dateindex"
					:class="{'date-disabled': beforeToday(date) || disabledDateFn(date)}"
					@tap="dateTap(date)"
				>
					<view 
						class="date-item"
						:class="{
							'date-active': showPrice(date) && isActiveDate(date),
							'date-active date-active2': !showPrice(date) && isActiveDate(date)
						}"
					>
						<text v-if="isToday(date)">今天</text>
						<text v-else>{{ date.date }}</text>
						<view class="price" v-if="showPrice(date)">¥{{ showPrice(date) }}</view>						
					</view>
				</view>
			</view>
		</view>
	</view>
</template>
复制代码

js

// 旅游产品 - 日历
export default {
	name: 'cus-calendar',
	props: {
		theme: {
			type: String,
			default: '#F87D72'
		},
		saleList: {
			type: Array,
			default: () => []
		},
		disabledDate: {
			type: Array,
			default: () => []
		},
		year: {
			type: Number,
			default: () => new Date().getFullYear()
		},
		month: {
			type: Number,
			default: () => new Date().getMonth()+1
		}
	},
	data() {
		return {
			newYear: '',
			newMonth: '',
			monthDay: [[], [], [], [], [], []],
			dateActive: {
				year: '',
				month: '',
				date: ''
			}
		}
	},
	watch: {
		month: {
			handler(val) {
				this.newYear = this.year;
				this.newMonth = this.month;
				this.generateCalendar(this.newYear, this.newMonth);
			},
			immediate: true
		}
	},
	methods: {
		// 验证日期是否有效:对应的月份是否有这一天
		validDate(year, month, date) {
			let time = new Date(`${year}-${month}-${date}`);
			let _year = time.getFullYear();
			let _month = time.getMonth() + 1;
			let _date = time.getDate();
			
			return _year === year && month === _month && date === _date
		},
		// 是否今天
		isToday({ year, month, date }) {
			let time = new Date();
			let _year = time.getFullYear();
			let _month = time.getMonth() + 1;
			let _date = time.getDate();
			
			return year === _year && month === _month && date === _date
		},
		// 今天之前
		beforeToday({ year, month, date }) {
			let time = new Date();
			let _year = time.getFullYear();
			let _month = time.getMonth() + 1;
			let _date = time.getDate();
			
			return year <= _year && month <= _month && date <= _date
		},
		// 禁用的日期
		disabledDateFn({ year, month, date }) {
			month = month < 10 ? (month+'').padStart(2, '0') : month;
			date = date < 10 ? (date+'').padStart(2, '0') : date;
			
			return this.disabledDate.includes(`${year}-${month}-${date}`);
		},
		// 是否选中
		isActiveDate({ year, month, date }) {
			const { month: _month, date: _date } = this.dateActive;
			return month === _month && date === _date;
		},
		// 点击有效的一天
		dateTap({ year, month, date }) {
			this.dateActive = {
				year,
				month,
				date
			};
			this.$emit('check-date', this.dateActive);
		},
		// 日期下面显示价格
		showPrice({ year, month, date }) {
			if (!year) return;
			
			month = month < 10 ? (month+'').padStart(2, '0') : month;
			date = date < 10 ? (date+'').padStart(2, '0') : date;
			
			let obj = this.saleList.find(item => item.date === `${year}-${month}-${date}`);
			return obj && obj.price
		},
		// 生成一个月的天数
		generateCalendar(year, month) {
			let that = this;
				let weekLen = new Array(7).fill(''); // 一周七天
				let weekday = new Date(`${year}-${month}-01`).getDay(); // 1号星期几
				
				// 重置
				this.monthDay = [[], [], [], [], [], []];
				
				// 生成一月对齐星期的天数,一周以周日开始
				weekLen.map((item, index) => {
					that.monthDay[0].push(
						index < weekday 
						? '' 
						: (index === weekday) 
							? {year, month, date: 1}
							: {year, month, date: that.monthDay[0][index-1].date+1}
					);
					that.monthDay[1].push({year, month, date: index + (7 - weekday + 1)});
					that.monthDay[2].push({year, month, date: that.monthDay[1][index].date + 7});
					that.monthDay[3].push({year, month, date: that.monthDay[2][index].date + 7});
					if (
						that.monthDay[3][index].date + 7 <= 31 && 
						this.validDate(year, month, that.monthDay[3][index].date + 7)
					) {
						that.monthDay[4].push({year, month, date: that.monthDay[3][index].date + 7});
					} else {
						that.monthDay[4].push('');
					}
					if (
						that.monthDay[4][index].date + 7 <= 31 && 
						this.validDate(year, month, that.monthDay[4][index].date + 7)
					) {
						that.monthDay[5].push({year, month, date: that.monthDay[4][index].date + 7});
					}
				})
			}
		}
	}
复制代码

css

<style scoped>
	.calendar-container {
		width: 100%;
		position: relative;
		color: #999;
	}
	.month-bg {
		position: absolute;
		top: 50%;
		left: 50%;
		/* color: #fcfcfc; */
		color: #f6f6f6;
		font-size: 60px;
		transform: translate(-50%, -50%);
		z-index: -1;
	}
	.week-title {
		padding: 20upx 40upx;
		display: flex;
		justify-content: space-between;
	}
	.week-title>text {
		flex: 1;
		text-align: center;
	}
	.weekend {
		color: #F87D72;
	}
	.week-month {
		display: flex;
		justify-content: flex-start;
		padding: 20upx 40upx;
		color: #2b2b2b;
	}
	.week-month>.date {
		flex: 14.285% 0 0;
		text-align: center;
	}
	.date-item {
		width: 60upx;
		height: 60upx;
		position: relative;
		left: 50%;
    margin-left: -30upx;
		line-height: 1;
	}
	.date-disabled {
		color: #999;
		pointer-events: none;
	}
	.price {
		color: #F87D72;
		font-size: 18upx;
	}
	.date-active {
		color: #fff;
	}
	.date-active::after {
		content: '';
		width: 140%;
		height: 140%;
		display: block;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		border-radius: 50px;
		background: linear-gradient(right, #F87D72, #F29E97);
		box-shadow: 0 6upx 16upx -6upx #F97C71;
		z-index: -1;
	}
	.date-active>.price {
		color: #fff;
	}
	.date-active2::after {
		transform: translate(-50%, -68%);
	}
</style>
复制代码

以上所述就是小编给大家介绍的《vue/uni-app之空手撕日历》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

引爆点

引爆点

[美] 马尔科姆·格拉德威尔 / 钱清、覃爱冬 / 中信出版社 / 2006-1 / 29.80元

这本书是《纽约客》杂志专职作家马尔科姆·格拉德威尔的一部才华横溢之作。他以社会上突如其来的流行风潮研究为切入点,从一个全新的角度探索了控制科学和营销模式。他认为,思想、行为、信息以及产品常常会像传染病爆发一样,迅速传播蔓延。正如一个病人就能引起一场全城流感;如果个别工作人员对顾客大打出手,或几位涂鸦爱好者管不住自己,也能在地铁里掀起一场犯罪浪潮;一位满意而归的顾客还能让新开张的餐馆座无虚席。这些现......一起来看看 《引爆点》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

html转js在线工具
html转js在线工具

html转js在线工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具