uni-app:踩坑路---scroll-view内使用fixed定位,无效的问题

前言:

        emmm,说起来这个问题整得还挺好笑的,本人在公司内,奋笔疾书写代码,愉快的提交测试的时候,测试跟我说,在苹果手机上你这个样式有bug,我倒是要看看,是什么bug。

安卓vs苹果

ok,我相信已经看出了差异了,安卓的遮罩层正常显示,而苹果的遮罩层只在我的绿色框内,被截断了,我赶忙看代码:

CustomItem.vue:自定义组件

蓝色的正方形,外加上一个遮罩层,点击蓝色方块的时候,显示遮罩层,遮罩层内写我的要展示的一些内容。

<template>
	<view class="">
		<view class="item" @click="visible = true"></view>

		<view class="mask" v-if="visible" @click="visible = false"></view>
	</view>
</template>

<script>
export default {
	name: 'CustomItem',
	data() {
		return {
			visible: false
		};
	}
};
</script>

<style lang="scss" scoped>
.item {
	width: 100rpx;
	height: 100rpx;
	background-color: #00aaff;
}
.mask {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background-color: rgba(#000, 0.5);
}
</style>

 父组件:引用CustomItem组件;

<template>
	<view class="index">
		<scroll-view scroll-x class="scroll">
			<view class="list">
				<custom-item class="item" v-for="i in 10" :key="i"></custom-item>
			</view>
		</scroll-view>
	</view>
</template>

<script>
import CustomItem from '@/components/CustomItem/index.vue';
export default {
	components: {
		CustomItem
	}
};
</script>

<style lang="scss" scoped>
.index {
	width: 100vw;
	height: 100vh;
	display: flex;
	align-items: center;
	justify-content: center;
}

.scroll {
	width: 400rpx;
	height: 150rpx;
	background-color: #aaaa7f;
}
.list {
	padding: 20rpx;
	display: flex;
	align-items: center;
	.item {
		margin-right: 20rpx;
	}
}
</style>

如此:就造成了上面的结果,在ios上显示不正常;于是我立马进入百度啦,问心一言啦,通义千问啦,最后哈,在社区找到了这么一个帖子;帖子看这里

emmm,寻求解决办法:

1.弃用scroll-view,改用view,使用css滚动;

<view class="list">
	<custom-item class="item" v-for="i in 10" :key="i"></custom-item>
</view>

<style lang="scss" scoped>
.list {
	width: 400rpx;
	height: 150rpx;
	background-color: #aaaa7f;
	padding: 20rpx;
	overflow-x: scroll;
	display: flex;
	align-items: center;
	.item {
		margin-right: 20rpx;
	}
}
</style>

2.如非必要,可以更改接口,其实上面的自定义组件CustomItem看着好像没有什么问题,是机型系统差异导致的,但是我们也并不能将全部原因归结于系统。 

当我们把它合起来看的话,就会发现在结构上似乎有一些问题了,遮罩层这一块的元素就需要循环10次,如果列表很长的话,那不就妥妥增加了很多的dom,浪费性能不说,结构设计也看着很怪, 所以有时候我们在封装组件的时候,不妨也这样考虑一下,可能这么写真的不太合适,最好的方案就是再划分下结构,只需要记得mask内的元素在放在scroll-view的外层即可!

<scroll-view scroll-x class="scroll">
	<view class="list">
		<view class="" v-for="i in 10" :key="i">
			<view class="item" @click="visible = true"></view>
			<view class="mask" v-if="visible" @click="visible = false"></view>
		</view>
	</view>
</scroll-view>

 告辞!

 

### 实现 uni-appscroll-view 组件的无缝循环滚动 为了实现在 `uni-app` 的 `scroll-view` 组件中的无缝循环滚动效果,可以采用设置定时器来自动触发滚动位置的变化,并通过监听滚动事件调整显示的内容。需要注意的是,在实现过程中应避免使用带有 `fixed` 属性的元素以防止视图随页面滚动而移动[^1]。 下面是一个简单的例子展示如何创建一个水平方向上的无限轮播: ```html <template> <view class="container"> <!-- 设置横向滚动 --> <scroll-view class="scroll-view_H" :scroll-x="true" @scroll="handleScroll" :scroll-left="scrollLeft" ref="scrollViewRef" > <block v-for="(item, index) in items.concat(items)" :key="index"> <view class="scroll-item">{{ item }}</view> </block> </scroll-view> </view> </template> <script> export default { data() { return { items: ['Item 1', 'Item 2', 'Item 3'], // 原始数据项 currentIndex: 0, timer: null, scrollLeft: 0 }; }, mounted() { this.startAutoScroll(); }, methods: { handleScroll(e) { const { detail } = e; let width = Math.round(detail.scrollWidth / (this.items.length * 2)); if ((detail.scrollLeft >= width && !this.isAnimating)) { this.currentIndex++; this.scrollToNext(); } }, scrollToNext() { this.$nextTick(() => { this.scrollLeft += this.$refs.scrollViewRef.offsetWidth; // 更新滚动距离 setTimeout(() => { this.resetPosition(); // 调整回初始状态 }, 50); }); }, resetPosition() { this.scrollLeft -= this.$refs.scrollViewRef.offsetWidth; this.currentIndex %= this.items.length; if (this.timer !== null) clearTimeout(this.timer); this.startAutoScroll(); }, startAutoScroll() { this.timer = setInterval(() => { this.scrollToNext(); }, 3000); // 自动切换时间间隔 } }, beforeDestroy() { clearInterval(this.timer); } }; </script> <style scoped> .container { position: relative; } .scroll-view_H { white-space: nowrap; overflow: hidden; height: 80px; } .scroll-item { display: inline-block; min-width: 100%; text-align: center; line-height: 80px; font-size: 36rpx; } </style> ``` 此代码片段展示了如何利用 Vue.js 和 CSS 来构建一个基本的水平无限轮播功能。这里的关键在于将原始列表重复一次并连接起来形成一个新的数组用于渲染,这样当到达最后一个项目时就可以平滑过渡到第一个项目上从而达到视觉上的连续性。同时设置了定时器每隔一段时间调用方法使容器向右滚动一定宽度的距离模拟自动播放的效果;并且在每次完成一轮完整的动画之后重置当前位置以便继续下一个周期的播放。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jay丶萧邦

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值