uni-app左右列表同步高亮滚动
最近在做点单小程序,其中左边是一级菜单,右边是商品列表,其中需求为左边点击高亮后,右边商品列表要滑动至相应的可视区域,同时右边商品列表滚动,左边的一级菜单可跟着可是区域的分类改变而高亮改变
最终运用到了uni-app中的额scroll-view组件,通过监听滚动和计算top值的方法,达到效果,demo代码如下:
<template> <view> <view class="flex scroll-contain"> <scroll-view style="width:30%" class="left-scroll border-right" :scroll-top="leftScrollTop" scroll-y> <view class="left-nav" :class="{'active': activeIndex == i}" v-for="i in 50" :key="i" @click="changeCate(i)">{{i}}</view> </scroll-view> <!-- #ifdef MP-WEIXIN --> <scroll-view style="width:70%" class="right-scroll" :scroll-top="rightScrollTop" @scroll="onRightScroll" scroll-y scroll-with-animation> <!-- #endif --> <!-- #ifdef MP-ALIPAY --> <scroll-view style="width:70%" class="right-scroll" :scroll-top="rightScrollTop" @scroll="onRightScroll" scroll-y scroll-with-animation scroll-animation-duration=200> <!-- #endif --> <view class="right-nav" v-for="(item,index) in 50" :key="index"> <view class="sticky">{{'category'+item}}</view> <view v-for="(item2 ,index2) in 10" :key="index2"> <text>{{'item'+item2}}</text> </view> </view> </scroll-view> </view> </view> </template> <script> export default { data() { return { containHeight: 0, // 滚动盒子的总高度 activeIndex: 0, // 左边当前菜单项的索引 leftDomsTop: [], rightDomsTop: [], leftScrollTop: 0, rightScrollTop: 0, } }, onReady() { const query = uni.createSelectorQuery().in(this); query.selectAll('.scroll-contain').boundingClientRect(data => { this.containHeight = data[0].height }).exec(); query.selectAll('.left-nav').boundingClientRect(data => { this.leftDomsTop = data.map(v => v.top) }).exec(); query.selectAll('.right-nav').boundingClientRect(data => { this.rightDomsTop = data.map(v => v.top - 30) }).exec(); }, methods: { // 点击左边导航栏 changeCate(index) { this.activeIndex = index this.rightScrollTop = this.rightDomsTop[index] }, // 右侧滚动 onRightScroll(e) { // 匹配当前scrollTop所处的索引 this.rightDomsTop.forEach((v, k) => { if (v < e.detail.scrollTop + 3) { this.activeIndex = k return false } }) const targetScrollTop = this.leftDomsTop[this.activeIndex] - this.containHeight * 0.5 const maxScrollTop = this.leftDomsTop[this.leftDomsTop.length - 1] - this.containHeight + (this .leftDomsTop[this.leftDomsTop.length - 1] - this.leftDomsTop[this.leftDomsTop.length - 2]) if (targetScrollTop == this.leftScrollTop) return this.leftScrollTop = Math.min(targetScrollTop, maxScrollTop) } }, } </script> <style lang="scss"> .scroll-contain { height: 80vh; } .active { background-color: #09f; } .flex { display: flex; } .sticky { position: sticky; top: 0; background-color: #fff; } </style>