uniapp实现楼层导航的核心技术要点:
1、scroll-view作为视图容器,
2、用其属性scroll-into-view,用于完成点击联动
3、uni.createSelectorQuery().selectAll();获取右侧所有元素信息,获取top值存入数组,用于计算滑动时需要的联动
代码示例(可直接复制查看)
<template>
<view class="bodys">
<view class="scroll_box" id="scroll_box">
<scroll-view :style="{ height: scrollHeight + 'rpx' }" scroll-y='true' class="left_box"
:scroll-into-view="leftIntoView">
<view class="left_item" v-for="(item,i) in leftArray" :key='i' @click="onLeft" :data-index="i"
:id="'left-'+i" :class="{select:i == leftIndex}">
{{item}}
</view>
</scroll-view>
<scroll-view :style="{ height: scrollHeight + 'rpx' }" @scroll="mainScroll" :scroll-into-view="scrollInto"
scroll-y='true' class="right_box" scroll-with-animation="true">
<slot></slot>
<view class="right_item" v-for="(item,i) in rightArray" :key='i' :id="'item-'+i">
<view class="rigth_title">
{{item.title}}
</view>
<view class="lis" v-for="(items,j) in item.list" :key='j'>
{{items}}
</view>
</view>
<view class="fill-last" :style="{ height: fillHeight + 'px' }"></view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
name: "side-navigation",
data() {
return {
leftArray: [],
rightArray: [],
scrollHeight: 400,
scrollInto: "",
leftIndex: 0,
topArr: [],
scrollTopSize: 0,
fillHeight: 0,
}
},
computed: {
leftIntoView() {
return `left-${this.leftIndex > 3 ? this.leftIndex - 3 : 0}`;
}
},
mounted() {
this.$nextTick(() => {
setTimeout(() => {
this.initScrollView().then(() => {
this.getListData();
});
}, 200);
});
},
methods: {
initScrollView() {
return new Promise((resolve, reject) => {
let view = uni.createSelectorQuery().select('#scroll_box');
view.boundingClientRect(res => {
console.log(res);
this.scrollTopSize = res.top;
this.scrollHeight = res.height;
this.$nextTick(() => {
resolve();
});
}).exec();
});
},
getListData() {
new Promise((resolve, reject) => {
uni.showLoading();
setTimeout(() => {
let [left, main] = [
[],
[]
];
for (let i = 0; i < 25; i++) {
left.push(`${i + 1}类商品`);
let list = [];
let r = Math.floor(Math.random() * 10);
r = r < 1 ? 3 : r;
for (let j = 0; j < r; j++) {
list.push(j);
}
main.push({
title: `第${i + 1}类商品标题`,
list
});
}
resolve({
left,
main
});
}, 1000);
}).then(res => {
uni.hideLoading();
this.leftArray = res.left;
this.rightArray = res.main;
this.$nextTick(() => {
this.getElementTop();
});
});
},
getElementTop() {
new Promise((resolve, reject) => {
let view = uni.createSelectorQuery().selectAll('.right_item');
view.boundingClientRect(data => {
resolve(data);
}).exec();
}).then(res => {
console.log(res);
let topArr = res.map(item => {
return item.top - this.scrollTopSize;
});
this.topArr = topArr;
let last = res[res.length - 1].height;
if (last - 20 < this.scrollHeight) {
this.fillHeight = this.scrollHeight - last + 20;
}
});
},
onLeft(e) {
const index = e.currentTarget.dataset.index;
this.scrollInto = `item-${index}`
},
mainScroll(e) {
let top = e.detail.scrollTop;
let index = 0;
for (let i = this.topArr.length - 1; i >= 0; i--) {
if (top + 2 >= this.topArr[i]) {
index = i;
break;
}
}
this.leftIndex = index < 0 ? 0 : index;
},
},
}
</script>
<style>
page,.bodys {
height: 100%;
}
.scroll_box {
display: flex;
height: 100%;
}
.left_box {
width: 30%;
}
.left_item {
height: 80rpx;
}
.lis {
height: 200rpx;
border-radius: 10rpx;
background: #808080;
color: #FFFFFF;
text-align: center;
line-height: 200rpx;
margin-bottom: 10rpx;
}
.select {
background-color: #4CD964;
}
</style>
实际实战
组件并不是顶高(不占全屏) scrollHeight 为内容最大高度,高度动态适配
onLoad(){
uni.getSystemInfo({
success: (result) => {
this.navHeight = result.statusBarHeight * (750 / result.windowWidth) + 88
this.scrollHeight = 2*result.windowHeight-yHeight-this.navHeight;
}
})
scrollHeight 滚动条里内容高度
windowHeight 获取到的手机高度
yHeight 在滚动条上方的高度(如果下方也有内容,也要加上)
navHeight 自定义导航栏高度
}
页面生命周期 onPageScroll() 监听页面滚动 页面在垂直方向已滚动的距离(单位px) 根据需求写
onPageScroll(e) {
this.scrollTop = e.scrollTop;
if(e.scrollTop>100){
this.params.opacity=1
this.colors='#281F14'
}else{
this.params.opacity=0
this.colors='#ffffff'
}
}
右侧滑动时
mainScroll(e) {
let top = e.detail.scrollTop;
let index = 0;
for (let i = this.topArr.length - 1; i >= 0; i--) {
if ((top + this.topArr[1]-1) >= this.topArr[i]) {
index = i;
break;
}
}
this.leftIndex = index < 0 ? 0 : index;
}
uniapp参考 还有一些vue和原生js参考,以后用到可以参考。 vue参考 原生态JS实现楼层导航案例
|