1.首先将元素用scroll-view这个标签包裹起来(注意这个容器里面只能有一个元素,另这个容器设置宽高也一定要给page设置高度,不然bindscroll就触发不了了)
2.这边对数据做了处理默认的数据结构
carList: [{
index: 'A',
cars: []
}, {
index: 'B',
cars: []
}, {
index: 'C',
cars: []
},]
这样的一个数据结构,将后台返回的数据通过循环分别塞入到数组对象 的数组cars中
wxml的代码
<!--pages/user/sfcCarBrand/sfcCarBrand.wxml-->
<block wx:if="{{step==1}}">
<view class='fiexed-box list-title' style='transform: translateY(-{{moveDistance}}px);'>
{{carBrand[listIndex].index}}
</view>
<scroll-view class="list-scroll {{config.search?'top':''}}" scroll-y="true" scroll-into-view="{{jumpNum}}" scroll-with-animation="{{config.animation}}" bindscroll="scroll">
<view>
<block wx:for='{{carBrand}}' w:key='index'>
<view id="{{'index'+index}}">
<view class='car-initials fixed-title-hock '>{{item.index}}</view>
<view class='tab list-name {{index1 === 0 ?"":"border"}}' data-name='{{item1.brandName}}' data-id='{{item1.id}}' catchtap='carBrand' wx:for="{{item.cars}}" wx:for-item='item1' wx:for-index='index1'>{{item1.brandName}}</view>
</view>
</block>
<!-- 右侧索引显示 -->
<view class='list-right-wrapper'>
<view class='right-item {{listIndex == index?"active":""}}' wx:for="{{rightArr}}" wx:key="rightArr" data-id="{{'index'+index}}" catchtap='jumpMt'>
{{item}}
</view>
</view>
</view>
</scroll-view>
</block>
<block wx:else>
<view class='tab' data-name='{{item.modelName}}' data-id='{{item.id}}' bindtap='carModel' wx:for="{{carModel}}">{{item.modelName}}</view>
</block>
<view>
</view>
wxss的代码
/* pages/user/sfcCarBrand/sfcCarBrand.wxss */
page{
height: 100%
}
.tab{
height: 80rpx;
background-color: white;
border-bottom: 1rpx solid #ececec;
color: #333;
line-height: 80rpx;
font-size: 28rpx;
padding-left: 20rpx;
}
.car-initials{
background: #EFF1F4;
height: 62rpx;
display: flex;
align-items: center;
padding-left: 32rpx;
font-size: 24rpx;
color: #424752;
}
.list-warpper {
position: relative;
width: 100%;
height: 100%;
box-sizing: border-box;
}
.list-scroll {
width: 100%;
height: 100%;
box-sizing: border-box;
}
.fiexed-box {
position: fixed;
z-index: 19;
width: 100%;
box-sizing: border-box
}
.list-title {
background: #EFF1F4;
color: #969797;
font-size: 28rpx;
padding-left: 30rpx;
height: 62rpx;
line-height: 62rpx;
}
.list-name {
position: relative;
font-size: 28rpx;
padding: 15rpx;
padding-left: 30rpx;
color: #42424C;
box-sizing: border-box
}
.list-name.border::after {
content: "";
position: absolute;
left: 30rpx;
right: 0;
top: 0;
height: 1px;
background: #f5f5f5;
}
/* 右侧字母显示 */
.list-right-wrapper {
position: fixed;
top: 120rpx;
right: 20rpx;
padding: 20rpx 0;
box-sizing: border-box;
z-index: 999;
}
.right-item {
display: flex;
justify-content: center;
align-items: center;
padding: 2rpx 10rpx;
font-size: 22rpx;
color: #333;
height: 40rpx
}
.right-item.active {
color: 000;
font-weight: bold;
font-size: 30rpx;
}
js的代码
// pages/user/sfcCarBrand/sfcCarBrand.js
const util = require('../../../utils/util.js');
Page({
/**
* 页面的初始数据
*/
data: {
step: 1,
rightArr: [], // 右侧字母展示
topGroup: [], // 内容高度数据
jumpNum: '', //跳转到那个字母
listIndex: 0,
moveDistance:0,
/**
* 配置项
*/
config: {
horizontal: false, // 第一个选项是否横排显示(一般第一个数据选项为 热门城市,常用城市之类 ,开启看需求)
animation: true, // 过渡动画是否开启
search: true, // 是否开启搜索
searchHeight: 45, // 搜索条高度
suctionTop: true // 是否开启标题吸顶
},
carList: [{
index: 'A',
cars: []
}, {
index: 'B',
cars: []
}, {
index: 'C',
cars: []
}, {
index: 'D',
cars: []
}, {
index: 'E',
cars: []
}, {
index: 'F',
cars: []
}, {
index: 'G',
cars: []
}, {
index: 'H',
cars: []
}, {
index: 'I',
cars: []
}, {
index: 'J',
cars: []
}, {
index: 'K',
cars: []
}, {
index: 'L',
cars: []
}, {
index: 'M',
cars: []
}, {
index: 'N',
cars: []
}, {
index: 'O',
cars: []
}, {
index: 'P',
cars: []
}, {
index: 'Q',
cars: []
}, {
index: 'R',
cars: []
}, {
index: 'S',
cars: []
}, {
index: 'T',
cars: []
}, {
index: 'U',
cars: []
}, {
index: 'V',
cars: []
}, {
index: 'W',
cars: []
}, {
index: 'X',
cars: []
}, {
index: 'Y',
cars: []
}, {
index: 'Z',
cars: []
}],
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
let that = this;
//这个地方时获取后台的数据
util.request(['', ''], [], res => {
if(res){
this.data.carList.forEach((i, index1) => {
res.forEach((item, index) => {
if (item.brandFirstWord == i.index) {
i.cars.push(item)
}
})
if (i.cars.length!=0){
that.data.rightArr.push(i.index)
}
})
var arr = []
this.data.carList.forEach((i, index1) => {
if(i.cars.length!=0){
arr.push(i)
}
})
that.setData({
carBrand: arr,
rightArr: that.data.rightArr
})
this.queryMultipleNodes();
}
})
},
/**
* 获取当前滚动索引
*/
currentIndex(y) {
let listHeight = this.data.topGroup
for (let i = 0; i < listHeight.length; i++) {
let height1 = listHeight[i]
let height2 = listHeight[i + 1]
if (!height2 || (y >= height1 && y < height2)) {
return i
}
}
return 0
},
/**
* 获取节点信息
*/
queryMultipleNodes() {
let self = this
const query = wx.createSelectorQuery().in(this);
query.selectAll('.fixed-title-hock').boundingClientRect((res) => {
res.forEach(function (rect) {
rect.top // 节点的上边界坐标
})
}).exec((e) => {
let arr = []
e[0].forEach((rect) => {
let num = 0
if (rect.top !== 0) {
//这个是如果有搜索框的话要减去搜索框的高度
// num = rect.top - (self.data.config.search ? self.data.config.searchHeight : 0)
num = rect.top
}
arr.push(num)
})
this.setData({
topGroup: arr
})
})
},
/**
* 监听滚动
*/
scroll(e) {
let top = e.detail.scrollTop
let index = this.currentIndex(top)
let list = this.data.topGroup
let distance = top - list[this.data.listIndex]
let num = -(list[this.data.listIndex + 1] - top - 40)
// 渲染滚动索引
if (index !== this.data.listIndex) {
this.setData({
// 'pos.oldIndex': index,
listIndex: index,
moveDistance: 40,
})
// 如果监听到 index 的变化 ,一定要return ,否则吸顶会先变化文字后运动,会闪烁
return
}
if (num < 0) num = 0
if (num !== this.data.moveDistance) {
this.setData({
moveDistance: num,
})
}
},
/**
* 右侧字母点击事件
*/
jumpMt(e) {
let jumpNum = e.currentTarget.dataset.id;
this.setData({
jumpNum
});
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})