uniapp 打造自用组件库 (七) 时间选择器

2,037 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

uniapp 打造自用组件库 (七) 时间选择器

前言

本文将带领读者使用uniapp封装一些常用组件,方便日后开发时重复使用,当然文中封装的组件不可能适配所有应用场景,但是我希望读者可以跟着我的思路实现出来,然后可以在此基础上优化改进为自己合适的,本人一个前端小菜鸡,希望大佬们可以不吝赐教,也是对我的技术水平的提升

时间选择器

需求

在开发的项目中,尤其是数据分析相关功能,经常会有多种时间筛选功能,需要按月、按年、按照时间范围来筛选,于是就封装了本组件,用于应对多种情况,划动选择后,点击确定后回调(可自行修改为收起时触发回调),返回类型,返回时间

image.png

效果展示

应用效果

image.png

应用代码
<view>
		<button type="default" @tap="isShow = true">选择时间 {{date}}</button>
		<Yselector :show.sync='isShow' @change='change'></Yselector>
	</view>
export default {
		data() {
			return {
				isShow:false,
				date:'',
			}
		},
		methods: {
			change(info){
				console.log('返回数据====>',info)
				this.date = ''
				for(let item of info){
					this.date = `${this.date} ${item}`
				}
				
			},
		}
	}

实现思路

利用uniapp的自定义选择器组件,在用户切换顶部按钮时生成选择项,然后选择完成后回调数据

完整实现代码

<template>
	<view class="bgBox">
		<view class="bg" @tap.stop="hide" :style="{height:show?'1000rpx':'0rpx'}">
			<view class="main" @tap.stop :style="{height:show?'600rpx':'0rpx'}">
				<view class="head">
					<view class="item" v-for="(i,index) in items" @tap="tapItems(index)" :style="{backgroundColor:itemsIndex == index?color:'#fff',color:itemsIndex == index?'#fff':'#333'}">
						{{i}}
					</view>
				</view>
				<view class="body">
					<picker-view :value='defaultDate' @change='change' :indicator-style='"padding:5px 0; border-top: 2px "+color+" solid;border-bottom: 2px "+color+" solid;"'>
						<picker-view-column :style="{marginLeft:index == 3?'30rpx':'10rpx' }" :key='index' v-for="(itemList,index) in infoList">
							<view :key='ind' v-for="(i,ind) in itemList">{{i}}</view>
						</picker-view-column>
					</picker-view>
				</view>
				<view class="foot" @tap="changeHide">
					<view>确定</view>
				</view>
			</view>
		</view>
	</view>
</template>
<script>
	export default {
		name: 'Yselector',
		props: {
			show: { //控制组件开关
				type: Boolean,
				default: false
			},
			color: {
				type: String,
				default: '#1E5EFF'
			}
		},
		data() {
			return {
				itemsIndex: 0,
				items: [
					'天',
					'月度',
					'年度',
					'时间范围',
					'全部',
				],
				infoList: [],
				defaultDate: [],
				Maindate: '',
				Maindate1:'',

			};
		},
		watch:{
			show(){
				if(this.show){
					this.tapItems(0)
				}
			}
		},
		methods: {
			getList(thisTime,type=true) {
				if(type){
					this.Maindate = thisTime
				}else{
					this.Maindate1 = thisTime
				}
				let timeList = thisTime.split('-')
				let ydate = new Date()
				let year = ydate.getFullYear()
				let day = new Date(parseInt(timeList[0]), parseInt(timeList[1]), 0); //获取当月有多少天
				let date = day.getDate()
				let yearList = []
				let monthList = []
				let dateList = []
				for (let i = 2000; i <= parseInt(year); i++) {
					yearList = [...yearList, i]
				}
				for (let i = 1; i <= parseInt(12); i++) {
					monthList = [...monthList, i]
				}
				for (let i = 1; i <= parseInt(date); i++) {
					dateList = [...dateList, i]
				}
				let mylist = [
					yearList,
					monthList,
					dateList
				]

				let infoList = []
				let yearIndex = yearList.indexOf(parseInt(timeList[0]))
				let defaultDate = []
				for (let i in timeList) {
					if (i == 0) {
						defaultDate = [yearIndex]
					} else {
						defaultDate = [...defaultDate, parseInt(timeList[i]) - 1]
					}
					infoList = [...infoList, mylist[i]]
				}
			
				return {
					defaultDate,
					infoList
				}
			},
			change({
				detail
			}) {
				let time = ''
				let time1 = ''
				for (let i in detail.value) {
					if (i < 3) {
						time += time ? `-${this.infoList[i][detail.value[i]]}` : `${this.infoList[i][detail.value[i]]}`
					} else {
						time1 += time1 ? `-${this.infoList[i][detail.value[i]]}` : `${this.infoList[i][detail.value[i]]}`
					}
				}
				let timeData =[]
				let timeData1 =[]
				if(time){
					timeData = this.getList(time)
				}
				if(time1){
					timeData1 = this.getList(time1,false)
		
				}
				
				let list = timeData1.infoList?[...timeData.infoList,...timeData1.infoList]:[...timeData.infoList]
				let defaultDateList = timeData1.infoList?[...timeData.defaultDate,...timeData1.defaultDate]:[...timeData.defaultDate]
				
				this.$set(this, 'defaultDate', defaultDateList)
				this.$set(this, 'infoList', list )
			},
			tapItems(index) {
				this.itemsIndex = index
				let date = new Date()
				if (this.items[index] == '天') {
					let time = `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`
					let timeData = this.getList(time)
					this.$set(this, 'defaultDate', timeData.defaultDate)
					this.$set(this, 'infoList', timeData.infoList)
				}
				if (this.items[index] == '月度') {
					let Mydate = `${date.getFullYear()}-${date.getMonth()+1}`
					let timeData = this.getList(Mydate)
					this.$set(this, 'defaultDate', timeData.defaultDate)
					this.$set(this, 'infoList', timeData.infoList)
				}
				if (this.items[index] == '年度') {
					let Mydate = `${date.getFullYear()}`
					let timeData = this.getList(Mydate)
					this.$set(this, 'defaultDate', timeData.defaultDate)
					this.$set(this, 'infoList', timeData.infoList)
				}
				if (this.items[index] == '时间范围') {
					let Mydate = `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`
					let timeData = this.getList(Mydate)
					let timeData1 = this.getList(Mydate,false)
					let list = [...timeData.infoList, ...timeData1.infoList]
					let defaultDateList = [...timeData.defaultDate, ...timeData1.defaultDate]
					this.$set(this, 'defaultDate', defaultDateList)
					this.$set(this, 'infoList', list)
				}
				if (this.items[index] == '全部') {
					let Mydate = `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`
					this.Maindate = Mydate
					this.changeHide()
				}

			},
			changeHide() {
				this.hide()
				let list = this.items[this.itemsIndex] == '全部'?[]:this.items[this.itemsIndex] == '时间范围'?[this.Maindate,this.Maindate1]:[this.Maindate]
				this.$emit('change', list);
			},
			hide(e) {
				this.$emit('update:show', false);
			}
		}
	};
</script>

<style lang="scss">
	.bgBox{
		position: relative;
		height: 0px;
		width: 100%;
	}
	.bg {
		position: absolute;
		width: 100%;
		height: 600rpx;
		left: 0;
		top: 100%;
		background: linear-gradient(180deg, rgba(0, 0, 0, 0.5) 10%, rgba(0, 0, 0, 0) 90%);
		z-index: 998;
		transition: 0.2s;

		.main {
			transition: 0.2s;
			width: 100%;
			height: 400rpx;
			background-color: #fff;
			border-radius: 0 0 25upx 25upx;
			display: flex;
			flex-direction: column;
			overflow: hidden;

			.head {
				display: flex;
				padding: 15rpx 30rpx;

				.item {
					transition: 0.1s;
					flex: 1;
					font-size: 12px;
					margin: 0 10rpx;
					text-align: center;
					padding: 10rpx 20rpx;
					border-radius: 10rpx;
					white-space: nowrap;

					&:active {
						opacity: 0.7;
						transform: scale(0.9);
					}
				}
			}

			.body {
				width: 100%;
				height: 100%;
				display: flex;
				justify-content: center;

				picker-view {
					margin-left: 20upx;
					height: 100%;

					picker-view-column {
						width: 100rpx;
						margin-left: 10upx;
					}

					view {
						font-size: 14px;
						font-weight: 400;
						color: rgba(51, 51, 51, 1);
						display: flex;
						flex-direction: column;
						align-items: center;
						justify-content: center;
					}
				}
			}

			.foot {
				display: flex;
				padding: 20rpx 30rpx;

				view {
					flex: 1;
					padding: 15rpx 0;
					border-radius: 30rpx;
					text-align: center;
					background-color: #1E5EFF;
					color: #FFFFFF;
					transition: 0.2s;

					&:active {
						opacity: 0.7;
						transform: scale(0.98);
					}
				}
			}
		}
	}
</style>