滑动验证组件---设置movable-view组件的x属性在微信小程序端失效的问题

场景

采用uniapp的movable-view组件实现滑动验证组件。

  • 流程
    • 滑块未滑到最右端时,回弹到原点
    • 滑块滑到最右端时,则显示滑动结束,不可再滑动

问题

频繁设置uniapp的movable-view组件的x属性,在H5端正常,但在微信小程序端则失效。

index.vue

<template>
	<view style="height: 100vh;width: 800rpx;display: flex;justify-content: center;align-items: center;">
		<wo-slider>
		</wo-slider>
	</view>
</template>

<script>
	import woSlider from './woSlider.vue'
	export default {
		components: {
			woSlider
		},
	}
</script>

<style>
</style>

woSlider.vue

<template>
	<view>
		<movable-area id="skidway" class="skidway">右滑全开
			<movable-view :damping="100" @touchend="onEnd" id="slider" :x="x" class='slider' direction="horizontal" @change="onChange" :disabled="isFinished">
				<view style="border-radius: 50%;height: 100%; width: 100%;overflow: auto;">
					<view v-if="isFinished" style="height: 100%">
						<view style="background: #1BA035; height: 100%; display: flex;justify-content: center;align-items: center;">
							<view class='movable-icon' style="background-image: url(/static/select-bold.svg)"></view>
						</view>
					</view>
					<view v-else style="height: 100%">
						<view style="background: #E5673B;height: 100%; display: flex;justify-content: center;align-items: center;">
							<view class='movable-icon' style="background-image: url(/static/arrow-right-bold.svg)"></view>
						</view>
					</view>
				</view>
			</movable-view>
		</movable-area>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				x: 0,
				oldX: 0,
				skidwayWidth: 0,  // 滑道长度
				sliderWidth: 0,  // 滑块长度
				isFinished: false,
				moveWidth: 0
			}
		},
		mounted() {
			const elemt = uni.createSelectorQuery().in(this)
			elemt.select('#skidway').boundingClientRect((data) => {
				this.skidwayWidth = data.width;  // 获取滑道长度
			}).exec()
			elemt.select('#slider').boundingClientRect((data) => {
				this.sliderWidth = data.width;  // 获取滑块长度
			}).exec()
		},
		methods: {
			onChange: function(e) {
				this.x = e.detail.x
				if(Math.round(this.x) >= Math.round(this.skidwayWidth - this.sliderWidth)) {
					this.isFinished = true  // 滑到最右端则完成
				}
			},
			onEnd: function(e) {
				if(Math.round(this.x) < Math.round(this.skidwayWidth - this.sliderWidth)) {
					setTimeout(()=>{
						this.x = 0  // 触摸松开的时候,未滑到最右端时则回到原位
					}, 100)
				}
			}
		}
	}
</script>

<style>
	.skidway{
		background-color: aliceblue;
	  width:200px;
	  height: 80rpx;
	  border-radius: 60rpx;
	  display:flex;
	  justify-content:center;
	  align-items:center;
		position: relative;
	}
	.slider{
	  width: 80rpx;
	  height: 80rpx;
	}
	.movable-icon{
	  width: 30rpx;
	  height: 30rpx;
	  background-size: 100% 100%;
	}
	.end-status {
		border-radius: 60rpx 0rpx 0rpx 60rpx;
		background-color: red;
		height: 100%;
		overflow: auto;
		position: absolute;
		left: 0;
		top: 0;
		display: flex;
		justify-content: center;
		align-items: center;
		color: #fff;
	}
</style>

  • H5端
    请添加图片描述
  • 微信小程序端
    请添加图片描述

原因

官方给出的解释:

由于app和小程序的架构是逻辑层与视图层分离,使用js监听拖动时会引发逻辑层和视图层的频繁通讯,影响性能。为了方便高性能的实现拖动,平台特封装了movable-area组件。

意思大概就是: 对频繁变化的组件属性值做了一些优化,将"多次变化"合为"少次变化"来执行。

官方给出的解决方案:
在这里插入图片描述
在这里插入图片描述
官方推荐第一种方法去解决这个问题,所以我们就来试试第一种。
第一种方法的思路就是:先用一个变量记录频繁变化的属性值,在最后的结束动作再用这个记录值来修改组件的属性值。

结果:成功解决在小程序端失效的问题

<template>
	<view>
		<movable-area id="skidway" class="skidway">右滑全开
			<movable-view :damping="100" @touchend="onEnd" id="slider" :x="x" class='slider' direction="horizontal" @change="onChange" :disabled="isFinished">
				<view style="border-radius: 50%;height: 100%; width: 100%;overflow: auto;">
					<view v-if="isFinished" style="height: 100%">
						<view style="background: #1BA035; height: 100%; display: flex;justify-content: center;align-items: center;">
							<view class='movable-icon' style="background-image: url(/static/select-bold.svg)"></view>
						</view>
					</view>
					<view v-else style="height: 100%">
						<view style="background: #E5673B;height: 100%; display: flex;justify-content: center;align-items: center;">
							<view class='movable-icon' style="background-image: url(/static/arrow-right-bold.svg)"></view>
						</view>
					</view>
				</view>
			</movable-view>
		</movable-area>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				x: 0,
				oldX: 0,
				skidwayWidth: 0,  // 滑道长度
				sliderWidth: 0,  // 滑块长度
				isFinished: false,
				moveWidth: 0
			}
		},
		mounted() {
			const elemt = uni.createSelectorQuery().in(this)
			elemt.select('#skidway').boundingClientRect((data) => {
				this.skidwayWidth = data.width;  // 获取滑道长度
			}).exec()
			elemt.select('#slider').boundingClientRect((data) => {
				this.sliderWidth = data.width;  // 获取滑块长度
			}).exec()
		},
		methods: {
			onChange: function(e) {
				this.oldX = e.detail.x  // 记录变化值
				if(Math.round(this.oldX) >= Math.round(this.skidwayWidth - this.sliderWidth)) {
					this.isFinished = true  // 滑到最右端则完成
				}
			},
			onEnd: function(e) {
				this.x = this.oldX  // 触摸松开,设置movable-view的x属性为记录的变化值
				if(Math.round(this.oldX) < Math.round(this.skidwayWidth - this.sliderWidth)) {
					setTimeout(()=>{  // 触摸松开的时候,未滑到最右端时则回到原位
						this.x = 0
						this.oldX = 0
					}, 100)
				}
			}
		}
	}
</script>

<style>
	.skidway{
		background-color: aliceblue;
	  width:200px;
	  height: 80rpx;
	  border-radius: 60rpx;
	  display:flex;
	  justify-content:center;
	  align-items:center;
		position: relative;
	}
	.slider{
	  width: 80rpx;
	  height: 80rpx;
	}
	.movable-icon{
	  width: 30rpx;
	  height: 30rpx;
	  background-size: 100% 100%;
	}
	.end-status {
		border-radius: 60rpx 0rpx 0rpx 60rpx;
		background-color: red;
		height: 100%;
		overflow: auto;
		position: absolute;
		left: 0;
		top: 0;
		display: flex;
		justify-content: center;
		align-items: center;
		color: #fff;
	}
</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狼性书生

谢谢鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值