1. 数据结构
首先,准备分组数据。例如:
Page({
data: {
list: [{
title: 'A',
items: ['Apple', 'Ant', 'Animal', ...(new Array(100).fill('列表内容-相信光吗'))],
},
{
title: 'B',
items: ['Banana', 'Bear', 'Ball', ...(new Array(100).fill('列表内容-相信光吗'))],
},
{
title: 'C',
items: ['Cat', 'Car', 'Cup', ...(new Array(100).fill('列表内容-相信光吗'))],
},
],
currentTitle: '', // 当前置顶的标题
},
});
2. 页面布局
在 WXML 中,使用 scroll-view
实现滚动,并通过 wx:for
渲染分组数据:
<view class="container">
<!-- 置顶标题 -->
<view class="sticky-title" wx:if="{{currentTitle}}">
{{currentTitle}}
</view>
<!-- 滚动内容 -->
<scroll-view
scroll-y
style="height: 100vh;"
bindscroll="onScroll"
scroll-top="{{scrollTop}}"
>
<block wx:for="{{list}}" wx:key="title">
<!-- 分组标题 -->
<view class="group-title" id="group-{{index}}">
{{item.title}}
</view>
<!-- 分组内容 -->
<view class="group-item" wx:for="{{item.items}}" wx:key="*this">
{{item}}
</view>
</block>
</scroll-view>
</view>
3. 样式
在 WXSS 中,设置样式:
/* 置顶标题 */
.sticky-title {
position: fixed;
top: 0;
left: 0;
right: 0;
background-color: #f8f8f8;
padding: 10px;
font-weight: bold;
z-index: 999;
}
/* 分组标题 */
.group-title {
background-color: #f0f0f0;
padding: 10px;
font-weight: bold;
}
/* 分组内容 */
.group-item {
padding: 10px;
border-bottom: 1px solid #e0e0e0;
}
4. 实现滚动逻辑
在 JS 中,监听 scroll-view
的滚动事件,计算当前显示的组,并更新置顶标题:
Page({
data: {
list: [{
title: 'A',
items: ['Apple', 'Ant', 'Animal', ...(new Array(100).fill('列表内容-相信光吗'))],
},
{
title: 'B',
items: ['Banana', 'Bear', 'Ball', ...(new Array(100).fill('列表内容-相信光吗'))],
},
{
title: 'C',
items: ['Cat', 'Car', 'Cup', ...(new Array(100).fill('列表内容-相信光吗'))],
},
],
currentTitle: '', // 当前置顶的标题
scrollTop: 0, // 滚动位置
groupTops: [], // 每个组的顶部位置
},
onLoad() {
// 计算每个组的顶部位置
this.calculateGroupTops();
},
calculateGroupTops() {
const query = wx.createSelectorQuery().in(this);
const groupTops = [];
this.data.list.forEach((group, index) => {
query.select(`#group-${index}`).boundingClientRect((rect) => {
groupTops[index] = rect.top;
if (index === this.data.list.length - 1) {
this.setData({ groupTops });
}
}).exec();
});
},
onScroll(e) {
const scrollTop = e.detail.scrollTop;
const groupTops = this.data.groupTops;
// 找到当前显示的组
for (let i = groupTops.length - 1; i >= 0; i--) {
if (scrollTop >= groupTops[i]) {
this.setData({ currentTitle: this.data.list[i].title });
break;
}
}
},
});
5. 优化
- 性能优化:如果数据量较大,可以使用虚拟列表(如
recycle-view
)优化渲染性能。 - 动画效果:可以为置顶标题添加动画效果,提升用户体验。
- 兼容性:确保在不同设备和屏幕尺寸下表现一致。
6. 完整代码
以下是完整的代码示例:
WXML
<view class="container">
<!-- 置顶标题 -->
<view class="sticky-title" wx:if="{{currentTitle}}">
{{currentTitle}}
</view>
<!-- 滚动内容 -->
<scroll-view
scroll-y
style="height: 100vh;"
bindscroll="onScroll"
scroll-top="{{scrollTop}}"
>
<block wx:for="{{list}}" wx:key="title">
<!-- 分组标题 -->
<view class="group-title" id="group-{{index}}">
{{item.title}}
</view>
<!-- 分组内容 -->
<view class="group-item" wx:for="{{item.items}}" wx:key="*this">
{{item}}
</view>
</block>
</scroll-view>
</view>
WXSS
.container {
position: relative;
}
.sticky-title {
position: fixed;
top: 0;
left: 0;
right: 0;
background-color: #f8f8f8;
padding: 10px;
font-weight: bold;
z-index: 999;
}
.group-title {
background-color: #f0f0f0;
padding: 10px;
font-weight: bold;
}
.group-item {
padding: 10px;
border-bottom: 1px solid #e0e0e0;
}
JS
Page({
data: {
list: [{
title: 'A',
items: ['Apple', 'Ant', 'Animal', ...(new Array(100).fill('列表内容-相信光吗'))],
},
{
title: 'B',
items: ['Banana', 'Bear', 'Ball', ...(new Array(100).fill('列表内容-相信光吗'))],
},
{
title: 'C',
items: ['Cat', 'Car', 'Cup', ...(new Array(100).fill('列表内容-相信光吗'))],
},
],
currentTitle: '',
scrollTop: 0,
groupTops: [],
},
onLoad() {
this.calculateGroupTops();
},
calculateGroupTops() {
const query = wx.createSelectorQuery().in(this);
const groupTops = [];
this.data.list.forEach((group, index) => {
query.select(`#group-${index}`).boundingClientRect((rect) => {
groupTops[index] = rect.top;
if (index === this.data.list.length - 1) {
this.setData({ groupTops });
}
}).exec();
});
},
onScroll(e) {
const scrollTop = e.detail.scrollTop;
const groupTops = this.data.groupTops;
for (let i = groupTops.length - 1; i >= 0; i--) {
if (scrollTop >= groupTops[i]) {
this.setData({ currentTitle: this.data.list[i].title });
break;
}
}
},
});
通过以上步骤,你可以在微信小程序中实现类似 t-indexes
的效果。