js
完整代码
<template>
<view class="content">
<view class="header"></view>
<view class="mainTopBox">
<view class="mainTop">
<uni-icons class="icon" type="bars" size="18"></uni-icons>
<view class="history">历史订单</view>
</view>
</view>
<view class="main">
<view class="categoryLeft">
<view class="menuItem" :class="{active:activeIndex === index}" v-for="(item,index) in list"
:key="item.id" @click="onClickItem(index)">
{{item.name}}
</view>
</view>
<scroll-view :scroll-top="rightScrollValue" scroll-y @scroll="rightScrollEnt" class="categoryRight" scroll-with-animation>
<view class="listBox" v-for="(item,index) in list" :key="item.id">
<view class="foodName">{{item.name}}</view>
<view class="itemBox" v-for="i in 5">
<image src="../../static/logo.png" mode=""></image>
<view class="itemBoxRight">
<view class="">白菜</view>
<uni-icons class="icon" type="person" size="30"></uni-icons>
</view>
</view>
</view>
<view class="noData">
没有更多了~
</view>
</scroll-view>
</view>
<view class="footer">
<image src="../../static/cart.png" mode=""></image>
<view class="btn">选好了</view>
</view>
</view>
</template>
<script setup>
import {nextTick,ref} from "vue";
import {onLoa} from "@dcloudio/uni-app"
onLoad(() => {
nextTick(()=>{
getHeightArr()
})
})
//滚动条最底部高度
const bottomValue = ref(0)
//滚动条最顶部高度
const topValue = ref(0)
//右边节点数组
const rightHeightArr = ref([])
//右边节点距离顶部的距离
const rightScrollValue = ref(0)
const list = ref([{
id: 1,
name: '荤菜'
},
{
id: 2,
name: '素菜'
},
{
id: 3,
name: '主食'
},
])
const activeIndex = ref(0)
//分类点击事件
const onClickItem = (e) => {
if(activeIndex.value === e) return
activeIndex.value = e
rightScrollValue.value = rightHeightArr.value[e]
}
//获取右边节点信息
const getHeightArr = ()=>{
const query = uni.createSelectorQuery();
query.select('.mainTop').boundingClientRect(data => { //获取滚动条最顶部高度
topValue.value = data.bottom
}).exec();
query.select('.footer').boundingClientRect(data => { //获取滚动条最底部高度
bottomValue.value = data.top - topValue.value
}).exec();
query.selectAll('.listBox').boundingClientRect(data => { //滚动区域最底部高度
rightHeightArr.value = data.map(item=>item.top - 70)
}).exec();
}
//右边滚动事件
const rightScrollEnt = (e)=>{
const { scrollTop,scrollHeight } = e.detail
const idx = rightHeightArr.value.findIndex((item,index,arr)=>scrollTop>=item && scrollTop < arr[index+1])
if(scrollTop + bottomValue.value >= scrollHeight - 35){ //scrollHeight是滚动区域最底部高度, - 35 是减去没有更多数据了(noData)的高度
activeIndex.value = rightHeightArr.value.length-1
}else{
activeIndex.value = idx
}
}
</script>
<style lang="scss" scoped>
.content {
display: flex;
flex-direction: column;
width: 100%;
height: 100vh;
.header {
background-color: #F5D463;
height: 100rpx;
}
.mainTopBox {
height: 80rpx;
background-color: #f8f8f8;
border-radius: 25rpx 25rpx 0 0;
margin-top: -20px;
.mainTop {
display: flex;
height: 100%;
align-items: center;
justify-content: flex-end;
.history {
font-size: 28rpx;
margin-right: 20rpx;
color: #00aaff;
}
}
}
.main {
flex: 1;
display: flex;
height: calc(100% - 280rpx);
.categoryLeft {
width: 25%;
background-color: #f8f8f8;
margin-right: 20rpx;
.menuItem {
height: 100rpx;
line-height: 100rpx;
text-align: center;
color: #7D7C82;
}
.active {
background-color: #fff;
color: #000;
}
}
.categoryRight {
width: 75%;
.listBox {
.foodName {
height: 100rpx;
line-height: 100rpx;
font-size: 30rpx;
color: #7D7C82;
position: sticky;
top: 0;
background-color: #fff;
}
.itemBox {
display: flex;
margin-bottom: 20rpx;
image {
width: 150rpx;
height: 150rpx;
border-radius: 10rpx;
}
.itemBoxRight {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 30rpx;
}
}
}
.noData {
font-size: 30rpx;
color: #aaa;
text-align: center;
padding: 10rpx 0 20rpx;
}
}
}
.footer {
height: 100rpx;
background-color: #f8f8f8;
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 20rpx 20px;
border-radius: 50rpx;
image {
width: 120rpx;
height: 120rpx;
}
.btn {
width: 180rpx;
height: 100%;
line-height: 100rpx;
text-align: center;
font-size: 34rpx;
font-weight: bold;
background-color: #F5D463;
border-radius: 0 50rpx 50rpx 0;
}
}
}
</style>