<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>
Uniapp左右联动案例代码
于 2024-08-26 23:37:18 首次发布