uniapp使用scroll-view实现左右分类联动

uniapp实现左右分类联动

仅供参考,根据个人所需调整

效果图

在这里插入图片描述


分类内容数据格式效果图

  • rectInfoList数据内容

在这里插入图片描述


template

<template>
	<view class="">
		<view class="slot-content category-wrap">
			<view class="category-box">
				<view class="cate-left">
					<scroll-view class="hFull" :scroll-top="scrollTop" scroll-y="true" show-scrollbar="false">
						<view class="cate-item ft24" :class="{active: current == index}" v-for="(item, index) in categoryList" @click="menuTab(index)" :key="index">
							{{item.name}}
						</view>
					</scroll-view>
				</view>
				
				<view class="cate-right">
					<scroll-view  class="hFull" :scroll-into-view="`cate${intoCurrent}`" scroll-y="true" show-scrollbar="false" @scroll="getCurrentHeight">
						<view class="cate-right-item" :id="`cate${index}`" v-for="(item, index) in categoryList" :key="item.id">
							<view class="fcb" :class="current == index ? '' : 'pdt20'">
								<view class="ft32 bold cate-title" :class="{active: current == index}">{{item.name}}</view>
								<view class="fc fold fc46" :class="item.isShow ? 'isFold' : ''" v-if="item.productList.length > 9" @click.stop="isShowItemTap(index)">
									<text class="ft24 pdr10">{{item.isShow ? '收起' : '展开'}}</text>
									<text class="iconfont iconright ft22"></text>
								</view>
							</view>
							<view class="grid-list" :class="[item.productList.length > 9 ? 'maxH' : '', item.isShow ? 'allItem' : '']">
								<view class="grid-item ft24 tc" :class="el.isCheck ? 'actives' : ''" v-for="(el, idx) in item.productList" :key="idx" @click="filtrateTap(item, idx)">
									<text>{{el.good_name}}</text>
								</view>
							</view>
						</view>
					</scroll-view>
				</view>
			</view>
			
			<view class="fixed-btn">
				<view class="fcb">
					<button class="fil-btn filtrate-reset" type="default" @click="resetFilTap">重 置</button>
					<button class="fil-btn filtrate-confirm" type="primary" @click="confirmFilTap">完 成</button>
				</view>
			</view>
		</view>
	</view>
</template>

js

<script>
	export default {
		data() {
			return {
				categoryList: [ // 测试数据
					{id: 1, name: '配件', isShow: false, productList: [
						{good_name: 'mi', isCheck: false},
					]},
					{id: 2, name: '手表', isShow: false, productList: [
						{good_name: 'mi1', isCheck: false},
					]}
                    // ...
				],
				current: 0, // 当前点击项
				intoCurrent:0, // 当前into-view
				rectInfoList:[], // 储存右侧内容元素的top bottom
				scrollTop:0, // 左侧导航栏距离顶部的位置
			}
		},
		onShow() {
			this.$nextTick(() => {
				// 获取右侧内容数据
				this.getRectInfo();
			})
		},
		methods: {
			/**
			 * @param {Object} index
			 * 切换菜单
			 */
			menuTab(index) {
				this.current = index;
				this.intoCurrent = `${index}`
			},
			/**
			 * @param {Object} index 下标
			 * 收起 or 展开
			 */
			isShowItemTap(index) {
				this.categoryList[index].isShow = !this.categoryList[index].isShow;
			},
			/**
			 * 获取元素与顶部之间的距离
			 */
			getRectInfo() {
				let top = 0;
				let bottom = 0;
				let temp = 0;
				for (let i = 0; i < this.categoryList.length; i++) {
					let view = uni.createSelectorQuery().in(this).select(`#cate${i}`);
					view.fields({
						size: true,
						rect: true
					}, data => {
						top = temp;
						bottom = top + data.height;
						temp = bottom;
						
						this.rectInfoList.push({ 'top': top, 'bottom': bottom })
					}).exec();
				}
			},
			/**
			 * @param {Object} e
			 * 滑动右侧内容联动左分类
			 */
			getCurrentHeight(e){
				let currentHeight = e.detail.scrollTop;
				
				this.rectInfoList.forEach((item, index)=>{
                    
					// 当前获取的盒子高度大于 top && 小于 bottom,联动选中左分类名称
					if(currentHeight >= item.top && currentHeight <= item.bottom){
						this.current = index;
						// 每次切换左菜单分类,让滚动条与顶部保持一定的距离
						this.scrollTop = index * uni.upx2px(88);
					}
				})
			},
			filtrateTap(item, cIdx) {
				item.productList[cIdx].isCheck = !item.productList[cIdx].isCheck;
			},
			resetFilTap() {
				
			},
			confirmFilTap() {
				
			},
		}
	}
</script>

css

  • 部分样式
<style lang="scss" scoped>
	$aux1: #4685F7;
	.fc46 {
		color: $aux1;
	}
	
	.grid-list {
		display: flex;
		flex-wrap: wrap;
		padding: 12rpx 0;
		overflow: hidden;
		.grid-item {
			@include wh(168rpx,76rpx);
			line-height: 76rpx;
			@include borderRadius(10rpx);
			@include bg(#F4F6F9);
			margin-bottom: 12rpx;
			&:not(:nth-child(3n)) {
				margin-right: 10rpx;
			}
		}
		
		.actives {
			@include bg(#FF6B00);
			color: $white;
		}
	}
	.fixed-btn {
		position: absolute;
		bottom: 0;
		width: 100%;
		z-index: 1;
		padding: 10rpx 32rpx;
		@include bg
		box-shadow: 0px -3px 8px rgba(0,0,0,0.0500);
		.fil-btn {
			margin: 0;
			width: 48.5%;
			@include borderRadius(10rpx);
		}
		.filtrate-confirm {
			@include bg($aux1);
		}
	}
	
	.fold {
		padding-right: 32rpx;
		.iconright {
			transform: rotate(90deg);
		}
	}
	.isFold {
		.iconright {
			transform: rotate(270deg);
			margin-left: 0;
			transform: all 5s;
		}
	}
	
	.category-wrap {
		height: calc(100vh - 300rpx);
		@include bg;
		position: relative;
		.category-box {
			display: flex;
			height: 100%;
		}
		.active {
			@include bg;
			color: $aux1;
		}
		.hFull {
			height: 100%;
		}
		.cate-left {
			@include wh(186rpx, 100%);
			@include bg(#F3F3F8);
			overflow-y: auto;
			-webkit-overflow-scrolling: touch;
			.cate-item {
				line-height: 88rpx;
				padding-left: 44rpx;
			}
		}
		.cate-right {
			flex: 1;
			height: calc(100% - 100rpx);
			padding-left: 28rpx;
			overflow-y: auto;
			-webkit-overflow-scrolling: touch;
		}
		.cate-right-item {
			&:not(:last-of-type) {
				border-bottom: 1rpx solid #E0E0E0;
			}
		}
		.maxH {
			max-height: 278rpx;
			.grid-item {
				&:nth-child(n+7):nth-child(-n+9) {
					margin-bottom: 25rpx;
				}
			}
		}
		.allItem {
			max-height: none;
			transition: all .1s;
			.grid-item {
				margin-bottom: 12rpx !important;
			}
		}
	}
</style>
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值