scroll-view 实现滑动显示,确保超出正常显示,小程序app,h5兼容

在uniapp 开开发的项目中,滑动操作是很多的

1.在插件市场使用了几款插件,但是都不太好用,要么是 显示的tab 过多,滑动到最后一个,当前显示那个跑左边显示不全,要么是滑动到最后一个后面的无法自动滑动,

2.基于借鉴别人写的以及自己处理了一下,目前感觉还行

3.使用需知道,显示的名字字段名字必须为name自己循环处理一下即可, 并且不能为空(实际情况也不会为空),目前发现bug

4.若有其他需求,请自行修改

第一步

新建组件scroll-easy.vue

<template>
	<view class="mianbox">
		<scroll-view scroll-x="true" :style="{  height: defH + 'rpx',background: `${debg}` }" class="contentMain"
			scroll-with-animation :scroll-left="scrollLeft">
			<view :style="{  height: defH + 'rpx',lineHeight: defH + 'rpx'}" v-for="(item, index) in getList"
				:key="index" class="scroll-item" @click="handItem(item,index)">
				<view :style="curIndex === index ? getActiveStyle : getDefaultStyle">
					{{ item.name }}
				</view>
			</view>
		</scroll-view>
	</view>
</template>
<script>
	export default {
		props: {
			list: { // 循环的数据
				type: Array,
				required: true,
				default: () => ([])
			},
			// 选中的下标
			index: {
				type: Number,
				default: 0
			},
			// 默认传入样式
			itemStyleDefault: {
				type: Object,
				default: () => ({})
			},
			// 默认传入选中样式
			itemStyleActive: {
				type: Object,
				default: () => ({})
			},
			// 切换部分高度
			defH: {
				type: String,
				default: '100'
			},
			// 切换整块的背景颜色
			debg: {
				type: String,
				default: '#f1f1f1'
			},
			// 名字过长是否缩写
			isNameEllipsis: {
				type: Boolean,
				default: false
			},
			// 超过数量
			exceed: {
				type: String,
				default: "4"
			},
		},

		data() {
			return {
				father_W: 0, // 导航区宽度
				scrollLeft: 0, // 横向滚动条位置
				curIndex: 0,
				// 这里是最初的样式 如果父组件不传下来
				defcss: {
					'color': '#999',
					'font-size': '14px',
					'height': '100%',
				},
				actcss: {
					'color': '#333',
					'font-size': '16px',
					'font-weight': 'bold',
					'height': '98%',
					'margin': '0 auto',
				}
			}
		},
		computed: {
			getList() {
				let arr = this.list
				if (this.isNameEllipsis) {
					arr.map((item) => {
						item.name = this.formatwordlimit(item.name, this.exceed)
					})
				} 
				return arr
			},
			getDefaultStyle() {
				return this.setStyle(this.defcss, this.itemStyleDefault)
			},
			getActiveStyle() {
				return this.setStyle(this.actcss, this.itemStyleActive)
			}

		},
		watch: {
			index: {
				handler(newVal, oldVal) {
					this.scrollLf(newVal)
					if (newVal) {
						this.scrollLf(newVal)
					}
				},
				immediate: true
			}
		},

		mounted() {
			//  初始化
			this.init()
		},
		methods: {
			formatwordlimit(cname, wordlength) {
				let nowLength = cname.length
				if (nowLength > wordlength) {
					return cname = cname.substr(0, wordlength) + '..'
				} else {
					return cname
				}
			},
			setStyle(target1, target2) {
				// 传进来的覆盖当前的 属性名要一致
				Object.assign(target1, target2)
				let style = ''
				Object.keys(target1).forEach((e) => {
					style += `${e}: ${target1[e]};`
				})
				return style
			},
			init() {
				// 返回一个 SelectorQuery 对象实例。可以在这个实例上使用 select 等方法选择节点,并使用 boundingClientRect 等方法选择需要查询的信息。
				const query = uni.createSelectorQuery().in(this);
				// 获取到循环父级盒子的宽度
				query.select('.contentMain').boundingClientRect(data => {
					// 拿到 scroll-view 组件宽度
					this.father_W = data.width
				}).exec();
				// 获取标题区域宽度,和每个子元素节点的宽度以及元素距离左边栏的距离
				query.selectAll('.scroll-item').boundingClientRect(data => {
					let len = data.length;
					for (let i = 0; i < len; i++) {
						//获取到每个元素距离最左边的距离
						this.getList[i].left = data[i].left;
						//  获取到每个元素 宽度
						this.getList[i].width = data[i].width
					}

				}).exec()
			},

			handItem(item, index) {
				this.scrollLf(index)
				this.$emit('handItem', item, index);
			},
			scrollLf(index) {
				this.curIndex = index;
				this.scrollLeft = this.getList[index].left - this.father_W / 2 + this.getList[index].width / 2;
			}
		}
	}
</script>

<style scoped>
	.mianbox {
		width: 100%;
		height: 100%;
	}

	.contentMain {
		white-space: nowrap;
	}

	.scroll-item {
		display: inline-block;
		margin: 0 20rpx;
		text-align: center;
	}
</style>

直接使用

例如在index.vue
import scrollEasy from '../../components/scroll-easy.vue'注意路径

<template>
	<view>
		1.默认样式
		<view>
			<scrollEasy :index='currindex' :list='category' @handItem='handthis' />
		</view>

		<view>
			1.默认选中下标
			<scrollEasy :index='currindex1' :list='category' @handItem='handthis' />
		</view>

		<view>
			2.自定义背景颜色
			<scrollEasy :list='category' debg='pink' :index='currindex' @handItem='handthis' />
		</view>


		<view>
			3.自定义tab 默认样式
			<scrollEasy :list='category' :index='currindex' @handItem='handthis'
				:item-style-default="{ 'font-size': '32rpx','color': 'red'}" />
		</view>

		<view>
			4.自定义tab 选中样式
			<scrollEasy :list='category' :index='currindex' @handItem='handthis'
				:item-style-active="{ 'font-size': '40rpx','font-weight': 'bold','color': 'red','border-bottom': '1px solid red'}" />
		</view>

		<view>
			5.自定义 是否开启名字过长限制字数....
			<scrollEasy :list='categoryOther' exceed='5' isNameEllipsis :index='currindex' @handItem='handthis' />
		</view>

		<view>
			6.自定义高度
			<scrollEasy debg='green' defH='180' :list='category' :index='currindex' @handItem='handthis' />
		</view>

		7.自定义布局
		<view class='combox'>
			<view class="left">
				<scrollEasy :list='category' :index='currindex' @handItem='handthis' />
			</view>
			<view class="right">
				站位部分
			</view>
		</view>

		<view style="display: flex;">
			<view v-for="(item,index) in category" :key="index" @click="addcurrindex(index)">
				<button style="flex: 1;">{{index}}</button>
			</view>
		</view>

	</view>
</template>

<script>
	import scrollEasy from '../../components/scroll-easy.vue'
	export default {
		components: {
			scrollEasy
		},
		data() {
			return {
				currindex: 0,
				currindex1: 2,
				category: [{
						id: 1,
						name: '面试信息1'
					},
					{
						id: 2,
						name: '面试信息2'
					},
					{
						id: 3,
						name: '面试信息3'
					},
					{
						id: 4,
						name: '面试信息4'
					},
					{
						id: 6,
						name: '面试信息5'
					},
					{
						id: 7,
						name: '面试信息6'
					},
					{
						id: 81,
						name: '充值中心7'
					}, {
						id: 62,
						name: '火车司机8'
					},
					{
						id: 73,
						name: '销售专员9'
					},
					{
						id: 84,
						name: '娱乐主播10'
					}
				],
				categoryOther: [{
						id: 1,
						name: '面试信息1'
					},
					{
						id: 2,
						name: '面试信息水电费2'
					},
					{
						id: 3,
						name: '面试信息3'
					},
					{
						id: 4,
						name: '面试信息4'
					},
					{
						id: 6,
						name: '面试信息四大分卫二5'
					},
					{
						id: 7,
						name: '面试信息6'
					},
					{
						id: 81,
						name: '充值中心7'
					}, {
						id: 62,
						name: '火车司机8'
					},
					{
						id: 73,
						name: '销售专员9'
					},
					{
						id: 84,
						name: '娱乐主播10'
					}
				]
			}
		},
		methods: {
			addcurrindex(index) {
				this.currindex = index
			},
			handthis(item, index) {
				console.log(item)
				console.log(index)
				this.currindex = index
			}
		}
	}
</script>

<style lang="scss" scoped>
	.combox {
		width: 100%;
		display: flex;
	}

	.left {
		flex: 1;
		width: 0;
	}

	.right {
		min-width: 100px;
		width: 100rpx;
		background: greenyellow;
		text-align: center;
		line-height: 100rpx;
	}
</style>
相关推荐
朴拙数科1 小时前
mysql报错解决 `1525 - Incorrect DATETIME value: ‘0000-00-00 00:00:00‘`
android·数据库·mysql
2401_844140182 小时前
同城到家预约上门服务解决方案:家政预约同城服务小程序
微信小程序·小程序·微信公众平台
peachSoda72 小时前
随手记:小程序获取胶囊宽高
小程序
说私域2 小时前
社区团购创新模式与新兴技术融合的深度探索:基于开源、AI 智能名片、2+1 链动模式与 S2B2C 商城小程序
人工智能·小程序·开源
微服务技术分享2 小时前
探店小程序:解锁商业新生态,定制未来
java·小程序·小程序搭建·探店小程序搭建
计算机软件程序设计3 小时前
高校失物招领小程序【源码+文档+安装+讲解】
小程序·程序设计·失物招领
说私域3 小时前
电商信任构建与创新模式:基于 2+1 链动模式与 S2B2C 商城小程序的分析
大数据·人工智能·微信小程序·小程序
刘争Stanley3 小时前
Android 15(V)新功能适配,雕琢移动细节之美
android·kotlin·android 15·android v
小狗爱世界3 小时前
深入解析Binder源码
android·binder