uniApp 手写一个步进器

我项目的需求是:

1.步进器支持异步加载(先调用接口确定是否有足够库存再决定是否增加/减少);

2.要求步进器支持长按进行数量增加 方便多张购票

3.不允许直接输入数值 

4.节流 每次点击触发接口请求的最低毫秒数可控

组件Vue文件 -> 

<template>
	<!-- 步进器组件 -->
	<view class="input-number-mybox">
		<button @touchstart.stop.prevent="btnTouchStart('minus')" @touchend.stop.prevent="clearTimer"
			:class="[MiunsDis]" :disabled="numberVal<=min" class="minus">
			<u-icon size="26" :color="MiunsColor_Dis" name="minus"></u-icon>
		</button>
		<view class="input-number-box">
			<input maxlength="2" disabled="true" class="input-number-class" type="number" :value="numberVal">
		</view>
		<button @touchstart.stop.prevent="btnTouchStart('add')" @touchend.stop.prevent="clearTimer" :class="[addDis]"
			:disabled="numberVal>=max" class="add">
			<u-icon size="26" :color="addColor_Dis" name="plus"></u-icon>
		</button>
	</view>
</template>

<script>
	export default {
		destroyed() {
			console.log('销毁时触发....清理定时器');
			this.timer = null;
			clearInterval(this.timer);
		},
		data() {
			return {
				timer: null, //长按定时器
				oneTimer: true, //单击节流
			}
		},
		methods: {
			ChangeVal(type) {
				//关闭软键盘 
				uni.hideKeyboard();
				
				
				//单击节流 
				if (!this.oneTimer) {
					return false
				}
				//设置为false
				this.oneTimer = false;
				//多少毫秒执行完毕后 才将状态改为 true
				setTimeout(() => {
					if (type == 'add') {
						let Addnum = Math.floor(Number(this.numberVal + this.step));
						if (Addnum > this.max) {
							console.log('大于最大值时不触发 并开启下一次点击避免无法 增减')
							return this.oneTimer = true;
						}
						this.$emit('ChangeNumber', Addnum);
					} else {
						let Minusnum = Math.floor(Number(this.numberVal - this.step));
						if (Minusnum < this.min) {
							console.log('小于最小值时不触发 并开启下一次点击避免无法 增减')
							return this.oneTimer = true;
						}
						this.$emit('ChangeNumber', Minusnum);
					}
					this.oneTimer = true;
				}, this.longTimer)

			},
			btnTouchStart(callback) {
				//触动 先调用一次增加或者减少方法
				console.log('type长按', callback);
				this.ChangeVal(callback);
				//如果没开启长按功能则直接return
				if (!this.longPress) {
					return
				}

				//清空定时器
				clearInterval(this.timer); //再次清空定时器,防止重复注册定时器
				this.timer = null;
				this.timer = setInterval(() => {
					// 执行加或减函数
					this.ChangeVal(callback);
				}, this.longTimer);
			},
			clearTimer() {
				//松开时立刻清除定时器
				this.$nextTick(() => {
					console.log('clearTimer...');
					clearInterval(this.timer);
					this.timer = null;
				})
			},
		},
		computed: {
			addDis() {
				return this.numberVal >= this.max ? 'disabled_use' : ''
			},
			MiunsDis() {
				return this.numberVal <= this.min ? 'disabled_use' : ''
			},
			MiunsColor_Dis() {
				return this.numberVal <= this.min ? 'rgb(200,201,204)' : 'rgb(50,50,51)';
			},
			addColor_Dis() {
				return this.numberVal >= this.max ? 'rgb(200,201,204)' : 'rgb(50,50,51)';
			}
		},
		props: {
			//绑定值
			numberVal: {
				type: [Number, String],
				default: 1
			},
			//控制每次点击增加的量
			step: {
				type: [Number, String],
				default: 1
			},
			//是否开启按住增加
			longPress: {
				type: Boolean,
				default: true
			},
			//开启按住增加时 每多少秒触发一次
			longTimer: {
				type: [Number, String],
				default: 600
			},
			//最小值
			min: {
				type: [Number, String],
				default: 1
			},
			//最大值
			max: {
				type: [Number, String],
				default: 99999
			}
		},

	}
</script>

<style lang="scss" scoped>
	.input-number-mybox {
		display: inline-flex;
		align-items: center;
		width: 212rpx;

		.input-number-box {
			// flex: 1;
			position: relative;
			background-color: none;
			text-align: center;
			background-color: rgb(242, 243, 245);
			height: 50rpx;
			margin: 0 6rpx;
			display: flex;
			justify-content: center;
			align-items: center;
			flex-direction: row;

			.input-number-class {
				font-size: 26rpx;
				color: rgb(50, 50, 51);
				padding: 0;
				min-height: 1.4em;
				line-height: 1.4em;
			}
		}


		.add,
		.minus {
			width: 50rpx;
			display: flex;
			align-items: center;
			justify-content: center;
			flex-direction: row;
			background-color: #eee;
			font-size: 28rpx;
			height: 50rpx;
			border-radius: 50%;
			color: rgb(50, 50, 51);
			flex-shrink: 0;
		}

		.disabled_use {
			background-color: rgb(247, 248, 250) !important;
		}
	}
</style>



父组件使用 参数可参考组件内部注释

<NumberBox :longTimer="450" :numberVal="form.count @ChangeNumber="ChangeNumberCount" />

父组件change事件

async ChangeNumberCount(Val) {

			console.log(Val, '传递过来的Val 是否需要修改..');
			this.isLoding = true; //开始加载
			if (this.form.count <= 0) {
				this.form.count = 1;
				this.$refs['playmentuToast'].show({
					title: '订单数量必须大于0!',
					type: 'warning'
				})
			} else {
				//等于1时不需要检查可购买数量
				if (Val == 1) {
					console.log('等于1时不需要检查可购买数量__');
					this.form.count = Val;
				}
				if (Val > 1) {
					//步进器点击增加时 先确认商品是否超出最大可购买数量
					let BuyCheck = await goodsBuyCheck(this.goodsId, Val);
					if (BuyCheck?.data?.code == 200) {
						console.log(BuyCheck, '正常赋值');
						this.form.count = Val;
					} else {
						console.log(BuyCheck, 'notnotnot');
						this.$u.toast(BuyCheck.data.message);
						this.isLoding = false; //结束加载
						return //阻止程序运行
					}
				}
			}
			console.log(this.form.count, '监听Change步进器');
			await this.findUserCouponListApi(); //获取可用列表优惠券列表
			await this.findUserNotCouPonList(); //获取用户不可用优惠券列表
			await this.findGoodCouOneApi(); //获取最优优惠券
			this.isLoding = false; //结束加载
			//调试
			// this.debugComputed();

		},

目前支持几个我需要用到的参数,其他参数暂未添加 ,单击节流是默认需要的,避免点击太快,如果不想要可以删掉定时器部分代码,仅此做记录。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值