小程序列表滚动卡顿怎么优化?

A. 晨羲 阅读 22

我在做微信小程序的长列表页面,数据一多滚动就特别卡,试过用 wx:for 渲染几百条记录,体验很差。是不是应该用虚拟列表?但不确定小程序支不支持。

目前是这样写的:

Page({
  data: {
    list: []
  },
  onLoad() {
    const bigList = Array.from({ length: 500 }, (_, i) => ({ id: i, name: 'Item ' + i }));
    this.setData({ list: bigList });
  }
})

有没有更高效的方式?比如只渲染可视区域的项?

我来解答 赞 6 收藏
二维码
手机扫码查看
1 条解答
Des.庆敏
小程序的wx:for渲染几百条确实会卡,必须用虚拟列表,只渲染可视区域的项。

微信小程序原生没虚拟列表,得自己动手。核心思路是:算好可见区域高度,监听滚动位置,动态截取数据,用绝对定位模拟滚动。

直接上代码,拿去改改:

Page({
data: {
list: [],
visibleData: [],
startIndex: 0,
itemHeight: 80,
visibleCount: 0,
totalHeight: 0,
offsetY: 0
},

onLoad() {
const bigList = Array.from({ length: 500 }, (_, i) => ({ id: i, name: 'Item ' + i }));
this.setData({ list: bigList });
this.calculateVisibleCount();
}, onReady() {
this.createSelectorQuery()
.select('#list-container')
.boundingClientRect(data => {
this.setData({
visibleCount: Math.ceil(data.height / this.data.itemHeight) + 3
});
this.updateVisibleData(0);
})
.exec();
},

onPageScroll(e) {
this.updateVisibleData(e.scrollTop);
},

updateVisibleData(scrollTop) {
const startIndex = Math.floor(scrollTop / this.data.itemHeight);
const { list, visibleCount } = this.data;
const endIndex = Math.min(startIndex + visibleCount, list.length);
const visibleData = list.slice(startIndex, endIndex);

this.setData({
startIndex,
visibleData,
offsetY: startIndex * this.data.itemHeight
});
}
})


对应的wxml:





{{item.name}}





对应的wxss:

.virtual-list {
position: relative;
width: 100%;
}
.list-inner {
position: absolute;
left: 0;
right: 0;
top: 0;
}
.list-item {
display: flex;
align-items: center;
padding: 0 20rpx;
border-bottom: 1rpx solid #eee;
box-sizing: border-box;
}


几点说明:

visibleCount 多加3条是为了防止快速滚动时出现白屏

itemHeight 固定值是最简单的做法,如果每项高度不一样,得用另外的方式计算偏移

如果数据量特别大(比如上万条),可以在滚动时做节流,避免频繁setData

这个方案跑起来应该流畅很多,几百条完全没问题。
点赞
2026-03-18 05:04