功能介绍
1、点击左侧分类导航栏页面右侧区域滚动到对应的分类数据,通过scroll-into-view实现,
2、滚动右侧区域,滚动到哪一分类的的区域,左侧导航栏对应分类的导航变为选中状态,通过滚动监听实现。
页面截图
代码实现
html结构
<template>
<view class="main">
<scroll-view scroll-y="true" class="left-content">
<view class="left-item" :class="{ 'activeItem': tabIndex == index }" v-for="(item,index) in leftData" :key="item.id" @click="clickLeftItem(index)">{{item.title}}</view>
</scroll-view>
<scroll-view scroll-y="true" class="right-content" :scroll-into-view="scrollId" scroll-with-animation @scroll="scrollEvt">
<view class="right-item" v-for="(item,index) in rightData" :key="item.id" :id="'item'+index">
<view class="title">
{{item.title}}
</view>
<view class="content">
<view class="content-item" v-for="itm in item.children" :key="itm.id">
{{itm.text}}
</view>
</view>
</view>
</scroll-view>
</view>
</template>
js
<script>
export default {
data() {
return {
tabIndex:0,
scrollId:'',
distanceList:[],
timer:null,
isLeftClick:false,
leftData:[{
title:'第一个',
id:10001
},
{
title:'第二个',
id:10002
},
{
title:'第三个',
id:10003
},
{
title:'第四个',
id:10004
},
{
title:'第五个',
id:10005
},
{
title:'第六个',
id:10006
}],
rightData:[{
id:'20001',
title:'第一部分标题',
children:[{
id:'30001',
text:'第一个子项'
},
{
id:'30002',
text:'第二个子项'
},
{
id:'30003',
text:'第三个子项'
},
{
id:'30004',
text:'第四个子项'
}]
},
{
id:'20002',
title:'第二部分标题',
children:[{
id:'30005',
text:'第一个子项'
},
{
id:'30006',
text:'第二个子项'
},
{
id:'30007',
text:'第三个子项'
}]
},
{
id:'20003',
title:'第三部分标题',
children:[{
id:'30008',
text:'第一个子项'
},
{
id:'30009',
text:'第二个子项'
},
{
id:'30010',
text:'第三个子项'
},
{
id:'30011',
text:'第四个子项'
}]
},
{
id:'20004',
title:'第四部分标题',
children:[{
id:'30012',
text:'第一个子项'
},
{
id:'30013',
text:'第二个子项'
}]
},
{
id:'20005',
title:'第五部分标题',
children:[{
id:'300014',
text:'第一个子项'
},
{
id:'300015',
text:'第二个子项'
}]
},
{
id:'20006',
title:'第六部分标题',
children:[{
id:'300016',
text:'第一个子项'
},
{
id:'300017',
text:'第二个子项'
},
{
id:'300018',
text:'第三个子项'
},
{
id:'300019',
text:'第四个子项'
}]
}]
}
},
mounted(){
setTimeout(()=>{
this.getDistanceToTop();
},500)
},
methods: {
clickLeftItem(index){
this.isLeftClick = true
this.tabIndex = index
this.scrollId = 'item'+index
},
getDistanceToTop() { //获取右侧各部分距离顶部的距离
let that = this
let selectorQuery = uni.createSelectorQuery().in(this);
selectorQuery.selectAll('.right-item').boundingClientRect(function(rects) {
rects.forEach(function(rect) {
that.distanceList.push(rect.top)
})
console.log('that.distanceList',that.distanceList);
}).exec()
},
// 元素滚动到顶部时,对应的左侧导航栏变为选中状态
scrollEvt(e){
// 点击左侧导航栏引起的滚动不做判断
if(this.isLeftClick){
this.isLeftClick = false
return
}
// 防抖
if(this.timer){
clearTimeout(this.timer)
}
this.timer = setTimeout(()=>{
let scrollTop = e.detail.scrollTop //滚动的高度
// 找到位于顶部元素的索引,距离大于滚动高度的第一个元素的上一个元素就是此时位于顶部的元素
let index = this.distanceList.findIndex(it=>{
// 滚动条的位置大于元素距离顶部位置的距离时,说明元素已经滑过了顶部
return (it > scrollTop)
}) -1
if(index == this.tabIndex) return
this.tabIndex = index
},200)
}
}
}
</script>
css
<style lang="less" scoped>
.main{
display: flex;
justify-content: space-between;
width: 100vw;
height: calc(100vh - 44px);
.left-content{
width: 250rpx;
height: 100%;
background-color: #E7E7E7;
.left-item{
width: 100%;
height: 100rpx;
text-align: center;
line-height: 100rpx;
}
}
.activeItem{
background-color: #fff;
color: skyblue;
}
.right-content{
flex: 1;
height: 100%;
background-color: #f4f4f4;
}
}
.content-item{
width: 100%;
height: 200rpx;
background-color: aqua;
margin-top: 20rpx;
}
.title{
padding: 15px 0 0 10px;
}
</style>