前言:微信小程序的代碼實現,uniapp與原生代碼差異不大,語法格式可對比swiper實現的原生代碼和scrollview實現的uniapp代碼。
參考資料:
微信小程序api>>https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html
獲取元素/組件與頂部的距離>>https://www.jianshu.com/p/fe72cff2b808
swiper實現的簡易demo>>https://blog.csdn.net/weixin_41599291/article/details/93650074
功能實現:
右側滾動,左側會對應高亮顯示;
左側是否重復點擊,右側顯示相應數據,置頂;
實現思路:
圍繞scroll-view組件的scroll-into-view和scroll-top屬性展開
巨坑:for(let i in this.topList)中的 i 屬於字符串,執行計算操作時必須先轉數字int
效果圖:

代碼:
<template>
<view>
<view style="text-align: center;">搜索欄</view>
<view class='productNav'>
<view class='left'>
<view :class="posi == 'id'+index ?'selected':'normal'" @tap='switchNav("id"+index, index)' v-for="(item, index) in dataList" :key="index">{{item.name}}</view>
</view>
<view class='right'>
<scroll-view scroll-y="true" class="scroll" @scroll="scroll" :scroll-into-view="posi" :scroll-top="scrollTop">
<view :id="item.id" v-for="(item, index) in dataList" :key="index">
<view class="title">{{item.name}}</view>
<view v-for="(subitem, i) in item.num" :key="i">{{item.name}}{{subitem}}</view>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
posi: '',
scrollTop: 0,
data: ['為您推薦','電腦','手機','美妝'] ,//模擬數據
dataList: [], //循環數據
dataEleHeight: [] ,//獲取data數組中各個元素的高度
topList: [], //計算得到各個元素與頂部的距離
scrollHeight: 500, //滾動區域的高度
flag: true //判斷左側是否做高亮顯示判斷
}
},
onLoad() {
//初始化數據,相當於請求數據
for (let i = 0; i < this.data.length; i++) {
let rand = parseInt(Math.random()*100,10);
let num = []
for(let j = 0; j < rand; j++) {
num.push(j);
}
let obj = {
id: 'id'+i,
name: this.data[i],
num: num
}
if(i == 0){
this.posi = obj.id
}
this.dataList.push(obj)
}
},
watch: {
dataEleHeight(val) {
if (val.length == this.dataList.length) {
//判斷是第幾個元素,高度設置為之前的元素高度之和
let top = 0
for (let i in this.dataEleHeight) {
if (i >= 0 && i < this.dataEleHeight.length) {
if(i != 0) {
top += this.dataEleHeight[i-1].height
}
this.topList.push(top);
}
}
}
console.log(this.topList)
}
},
mounted(){
let that = this
for (let i = 0; i < this.dataList.length; i++) {
//獲取元素屬性最好是在渲染之后執行,避免獲取空值
uni.createSelectorQuery().in(this).select('#'+this.dataList[i].id).boundingClientRect(function(rect){
let obj = {
id: that.dataList[i].id,
height: rect.height
}
that.dataEleHeight.push(obj);
}).exec();
}
},
methods: {
scroll(e) {
let index = this.posi.substring(2)
//如果點擊了左側分類,則不做左側高亮顯示判斷
if (this.flag) {
for(let i in this.topList){
if (i < this.topList.length - 1 && this.topList[i] <= e.detail.scrollTop && e.detail.scrollTop < this.topList[parseInt(i) + 1]) {
this.posi = this.dataList[i].id
break;
}
this.posi = this.dataList[i].id
}
}
this.flag = true
this.scrollTop = e.detail.scrollTop //解決重復點擊菜單時右側數據不變的問題
},
switchNav: function (e, index) {
this.flag = false
if(this.posi != e){
this.posi = e
} else {
//重復點擊一樣要定位到最開頭的位置
this.scrollTop = this.topList[index];
}
}
}
}
</script>
<style>
.productNav{
display: flex;
flex-direction: row;
font-family: "Microsoft YaHei"
}
.left{
width: 25%;
font-size: 30rpx;
background-color: #f4f4f4;
}
.left view{
text-align: center;
height: 90rpx;
line-height: 90rpx;
}
.selected{
background-color: #fff;
border-left: 2px solid #E54847;
font-weight: bold;
color: #E54847;
}
.normal{
background-color: #f4f4f4;
border-bottom: 1px solid #f2f2f2;
}
.right{
width:75%;
margin: 0;
}
.scroll{
height: 500px;
text-align: center;
}
.title{
background: #E54847;
color: white;
}
</style>
