Uniapp左右联动案例代码

<template>
	<view>
		<view class="aside-main">
			<scroll-view scroll-y class="scroll-Y1" :style="'height:'+ mainH" scroll-with-animation>
				<view :class="num==index?'active':'active2'" v-for="(item,index) in asideList" :key="index"
					@click="asid(index)">{{item.title}}
				</view>
			</scroll-view>
			<!-- 右侧滑动区 -->
			<scroll-view scroll-y class="scroll-Y2" :style="'height:'+ mainH" :scroll-into-view="rightview"
				scroll-with-animation @scroll="scrollright" @scrolltoupper="scrolltop" @scrolltolower="scrollbuttom">
				<!-- 功能区节点 -->
				<view v-for="(item,index) in asideList" :key="index" class="min" :id="'rightIndex'+index">
					<view v-for="(i,j) in item.list" :key="j" class="minmi">
						<image class="imgPic" :src="i.url" mode=""></image>
						<view class="rightContainer">
							<view class="foodName">
								{{item.title}}
							</view>
							<view class="foodPrice">
								<view class="priceflex">
									<text class="zero"></text>
									{{i.price}}
								</view>
								<view class="shopCar iconfont-themeColor-write">
									选套餐
								</view>
							</view>
						</view>
					</view>
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				mainH: '400px',
				num: 0,
				leftview: '',
				rightview: '',
				// 所有的节点坐标
				nodes: [],
				asideList: [{
						title: "双人套餐",
						list: new Array(50).fill({
							url: "https://gitee.com/xiaojisengren/food-speed-order-img/raw/master/defaultImg/tangshi.png",
							name: '双人套餐',
							price: 32
						})
					},
					{
						title: "多人套餐",
						list: new Array(50).fill({
							url: "https://gitee.com/xiaojisengren/food-speed-order-img/raw/master/defaultImg/tangshi.png",
							name: '双人套餐',
							price: 32
						})
					},
					{
						title: "粥",
						list: new Array(50).fill({
							url: "https://gitee.com/xiaojisengren/food-speed-order-img/raw/master/defaultImg/tangshi.png",
							name: '双人套餐',
							price: 32
						})
					},
					{
						title: "饺子",
						list: new Array(50).fill({
							url: "https://gitee.com/xiaojisengren/food-speed-order-img/raw/master/defaultImg/tangshi.png",
							name: '双人套餐',
							price: 32
						})
					},
					{
						title: "小吃",
						list: new Array(50).fill({
							url: "https://gitee.com/xiaojisengren/food-speed-order-img/raw/master/defaultImg/tangshi.png",
							name: '双人套餐',
							price: 32
						})
					},
					{
						title: "汤",
						list: new Array(50).fill({
							url: "https://gitee.com/xiaojisengren/food-speed-order-img/raw/master/defaultImg/tangshi.png",
							name: '双人套餐',
							price: 32
						})
					}
				]
			}
		},
		created() {
			// 调用uniapp的api获取系统信息,如浏览器可视区高度
			// 实现向下滑动,只有内容区可以滑动
			uni.getSystemInfo({
				success: (res) => {
					// 将upx转换成px
					// 可视区高度减去导航栏高度
					this.mainH = res.windowHeight - uni.upx2px(88) + 'px';
				}
			})
			// 得到页面加载完成时所有的.min节点的坐标位置,主要为top值
			this.coordinate()
		},
		methods: {
			// 侧边栏切换
			asid(index) {
				// 变色
				this.num = index
				// 通过uniapp的scroll-into-view实现与右侧功能区节点的切换联动
				this.rightview = 'rightIndex' + index
			},
			// 滑动触顶事件
			scrolltop() {
				this.num = 0
			},
			// 滑动触底事件
			scrollbuttom() {
				this.num = this.nodes.length - 1
			},
			// 滑动右边内容区实现与左侧菜单栏联动效果
			// 监听滑动事件
			scrollright(e) {
				// 每一次滑动之前都做一遍跟随,用来解决侧边栏切换不联动问题(重要!!!不加是有bug的)
				this.asid()
				// 拿到滑动的距离(记住初始滑动距离是0!!很重要)
				console.log('滑动的距离', e.detail.scrollTop)
				// 遍历存储所有节点top坐标的数组nodes(默认从下标1开始,因为初始状态的左侧菜单栏与右侧功能区就是对应的!!)
				for (let i = 1; i < this.nodes.length; i++) {
					// 判断滑动的距离+初始节点的top值!!(这里就是为什么在上面特意提醒要牢记滑动距离的初始值是0的原因,这里将滑动距离加上初始节点的top值是为了将二者放在一个'水平线'上,便于后面比较)是否大于等于当前功能区节点的top值并且小于等于下一个的节点的top值,如果满足条件将切换左侧菜单栏变色的标识符num的值变为当前节点的i。同时需额外判断滑动的距离+初始节点的top值是否大于最后一个功能区节点的top值,因为如果不单独判断的话,原判断逻辑针对最后一个节点是满足不了并条件的。判断头部同理,同时需搭配触顶与触底事件。
					if (e.detail.scrollTop + this.nodes[0] >= this.nodes[i] && e.detail.scrollTop + this.nodes[0] <= this
						.nodes[i + 1]) {
						this.num = i
					} else if (e.detail.scrollTop + this.nodes[0] < this.nodes[1]) {
						this.num = 0
					} else if (e.detail.scrollTop + this.nodes[0] > this.nodes[this.nodes.length - 1]) {
						this.num = this.nodes.length - 1
					}
				}
			},
			// 获取右侧内容区每个指定节点的坐标信息(即左侧菜单栏所对应的每一个功能区的顶部坐标),该方法只在created生命周期中执行一遍即可
			coordinate() {
				const query = uni.createSelectorQuery().in(this);
				query.selectAll(".min").boundingClientRect((data) => {
						// 获取每一个功能区的全部坐标对象(数组形式)
						console.log("得到布局位置信息" + JSON.stringify(data));
						console.log("节点离页面顶部的距离为" + data.top);
						console.log(data)
						// 遍历每一个功能区的全部坐标对象(数组形式),拿到所有的top坐标
						for (let i = 0; i < data.length; i++) {
							console.log("每个节点的top坐标", data[i].top)
							// 将每个top坐标push进一个空数组nodes中
							this.nodes.push(data[i].top)
						}
						console.log("nodes", this.nodes)
					})
					.exec();
			}
		}
	}
</script>

<style lang="scss">
	.active {
		font-size: 20upx;
		color: #F9BE3E;
	}

	.active2 {
		font-size: 20upx;
	}

	.min {
		display: flex;
		flex-direction: row;
		justify-content: space-around;
		flex-wrap: wrap;
	}

	.minmi {
		display: flex;
		width: 592upx;
		margin-left: 25upx;
		padding-top: 51upx;

		.imgPic {
			width: 208upx;
			height: 167upx;
			border-radius: 10upx;
			margin-left: 20upx;
		}

		.rightContainer {
			display: flex;
			flex-direction: column;
			height: 167upx;
			justify-content: space-between;
			align-items: flex-start;
			padding-left: 18upx;
			padding-right: 18upx;
			flex: 1;

			.foodName {
				font-weight: 700;
				font-size: 25upx;
			}

			.foodPrice {
				display: flex;
				justify-content: space-between;
				width: 375upx;
				color: #F9BE3E;

				.priceflex {
					display: flex;
					align-items: center;

					.zero {
						font-size: 15upx;
					}
				}

				.shopCar {
					background-color: #F9BE3E;
					border-radius: 45upx;
					width: 112upx;
					height: 45upx;
					font-size: 25upx;
					text-align: center;
					line-height: 46upx;
				}
			}
		}
	}

	.aside-main {
		width: 100%;
		display: flex;
		flex-direction: row;
		justify-content: space-between;
		box-sizing: border-box;
	}

	.scroll-Y1 {
		flex: 1;
		box-sizing: border-box;
	}

	.scroll-Y1 view {
		text-align: center;
		padding-top: 33upx;
		padding-bottom: 33upx;
		padding-left: 23upx;
		padding-right: 23upx;
	}

	.scroll-Y2 {
		flex: 3;
		box-sizing: border-box;
	}

	.scroll-Y2 view {
		text-align: center;
		/* margin:20upx; */
	}

	.icon {
		width: 50upx;
		height: 50upx;
		margin-top: 10upx;
	}

	.icon1 {
		width: 30upx;
		height: 30upx;
		position: absolute;
		top: 15upx;
		left: 10upx;
	}

	.btn {
		width: 140upx;
		height: 60upx;
		line-height: 60upx;
		margin: 0;
		padding: 0;
		font-size: 30upx;
	}

	.serch {
		height: 60upx;
		flex: 2;
		margin-left: 20upx;
		margin-right: 20upx;
		box-sizing: border-box;
		border: solid 1upx #ccc;
		border-radius: 10upx;
		position: relative;
	}

	.serch input {
		height: 60upx;

		margin-left: 60upx;
	}
</style>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

萧寂173

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

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

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

打赏作者

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

抵扣说明:

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

余额充值