# 主要思路
- 首字母检索项的值对应数据列的元素的id
- 通过
createSelectorQuery
获取检索项每项的坐标信息(因为目前通过touchmove
无法直接获取到手指所在元素) - 通过点击/滑动获取到首字母检索项的值,点击直接通过点击事件获取检索项的值,滚动通过
touchmove
获取手指所在的坐标信息,判断是否在某一个检索项范围中 - 动态设置
scroll-view
的scroll-into-view
(opens new window)的值,达到滚动到对应id的检索数据列
# wxml
<!-- 数据列表两层循环,外层为分组 ,内层为列表 -->
<view>
<scroll-view scroll-into-view="{{scrollIntoVw}}"
scroll-y
scroll-with-animation
enable-back-to-top>
<view wx:for="{{list}}" wx:key="index">
<!-- 设置id,即对应检索滚动的位置 -->
<view id="{{item.group}}"
class="group-type">{{item.group}}</view>
<view wx:for="{{item.li}}"
wx:for-item="itm"
wx:for-index="idx"
wx:key="idx"
data-i="{{index + '_' + idx}}"
bindtap="onBrand">
<view class="group-item">
<view>
<image></image>
</view>
<text>{{itm.name}}</text>
</view>
</view>
</view>
</scroll-view>
</view>
<!--首字母检索列表-->
<view class="wrap-index" catch:touchmove="touchmove">
<view class="index {{flag == item ? 'active' : ''}}"
wx:for="{{abc}}" wx:key="index"
data-id="{{item}}" bindtap="onIndex">{{item}}</view>
</view>
# wxss
scroll-view {
height: 100vh; // 设置高度才能滚动
}
.group-type {
font-size: 24rpx;
color: #666;
background-color: #F7F7F7;
padding: 4rpx 40rpx;
}
.group-item {
display: flex;
align-items: center;
font-size: 28rpx;
padding: 8rpx 22rpx;
background-color: #fff;
}
.group-item image {
width: 80rpx;
height: 80rpx;
background-color: #F7F7F7;
margin-right: 20rpx;
}
.wrap-index {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16rpx;
position: fixed;
top: 0;
bottom: 0;
right: 0;
z-index: 100;
}
.wrap-index>view {
width: 34rpx;
height: 34rpx;
font-size: 24rpx;
text-align: center;
color: #666;
border-radius: 50%;
padding: 6rpx;
}
.wrap-index>.active {
color: #fff;
background-color: #CC2B22;
}
# js
data: {
flag: 'A', // 设置检索项选中样式
scrollIntoVw:'', // scroll-into-view
indexPos: [], // 储存检索项位置信息
// 列表数据结构
list: [
{
group: 'A', li: [
{ name: '奥迪' },
{ name: '阿尔法·罗密欧' },
...
]
}, {
group: 'B', li: [
{ name: '比亚迪' },
{ name: '宝马' },
...
]
}
],
abc: [] // 首字母检索数组,直接定义变量或方法生成
},
touchmove(e) {
// 节流
let now = new Date().getTime()
if (now - timestamp < 50) return
timestamp = now
// 双指/多指/误触
if (e.touches.length > 1) return
// 判断手指滑动位置坐标是否在元素top和bottom之间
let y = e.touches[0].clientY
let indexPos = this.data.indexPos
for (const item of indexPos) {
if (y >= item.top && y <= item.bottom) {
this.scroll2Vw(item.dataset.id)
break
}
}
},
scroll2Vw(id) {
this.setData({
scrollIntoVw: id,
flag: id
})
},
// 点击获取id
onIndex(e) {
let id = e.currentTarget.dataset.id
this.scroll2Vw(id)
},
onReady() {
// 存储检索项位置信息
let self = this
wx.createSelectorQuery()
.selectAll('.wrap-index .index')
.boundingClientRect()
.exec(function (res) {
let indexPos = res[0]
self.setData({ indexPos })
})
}
# e.touches数据结构
[{
clientX: 356
clientY: 155
force: 1
identifier: 0
pageX: 356
pageY: 155
}, ...]
# indexPos数据结构
[{
bottom: 93.5,
dataset: { id: "A" },
height: 19,
id: "",
left: 381,
right: 414,
top: 74.5,
width: 33
}, ...]