首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >小程序长列表滚动卡顿?虚拟滚动与增量渲染实战

小程序长列表滚动卡顿?虚拟滚动与增量渲染实战

原创
作者头像
用户5658160
发布2026-09-15 14:04:52
发布2026-09-15 14:04:52
440
举报

导读:商品列表、订单列表、消息列表一长,小程序就卡成幻灯片——白屏、掉帧、内存暴涨,用户直接划走。这篇文章给出一套可落地的长列表优化方案:虚拟滚动怎么算可视区、增量渲染怎么分批出图、内存怎么控制,每步带代码要点与坑位提示。

一、先明白卡顿的根源

小程序长列表卡顿有三个叠加原因:节点太多(几千个 view 全部渲染进 DOM)、图片太重(首屏外图片也全部下载解码)、setData 全量更新(每次数据变更都把整页数据塞给渲染层)。优化思路只有一条:只渲染用户看得见的那部分,其余的全部延后或丢弃。

二、虚拟滚动:只渲染可视区

虚拟滚动的核心是:固定行高(或预估行高),根据滚动位置算出可视区起止索引,只渲染这个区间加上前后缓冲区的节点:

代码语言:javascript
复制
// 可视区起止索引计算
const start = Math.floor(scrollTop / rowHeight) - bufferCount;
const end = Math.ceil((scrollTop + viewportHeight) / rowHeight) + bufferCount;
const visibleItems = list.slice(Math.max(0, start), end);

缓冲区(bufferCount 取 5-10)用来消除快速滑动时的白屏。关键点是列表容器高度固定、内容用绝对定位撑开总高度,否则滚动位置对不上。小程序里配合 scroll-view 或页面滚动事件实现。

三、增量渲染:分批出图不阻塞

虚拟滚动解决节点数,图片加载还得单独处理。技巧是按需加载 + 分批

  • 图片用懒加载,只加载可视区内的;
  • 滑动停止后再加载下一批,而不是边滑边拉;
  • 图片组件用占位背景色,加载完成再替换,避免布局抖动。
代码语言:javascript
复制
// 滑动停止后 300ms 触发下一批加载
let timer;
onScroll() {
  clearTimeout(timer);
  timer = setTimeout(loadNextBatch, 300);
}

四、setData 瘦身:别把整个列表推给渲染层

小程序 setData 的代价和传输数据量成正比。长列表场景必须只更新变化的行

代码语言:javascript
复制
// 错误:整个列表重新 setData
this.setData({ list: newList });

// 正确:只更新变化的行
this.setData({ [`list[${index}].status`]: newStatus });

配合 pureDataPattern(纯数据字段)把不参与渲染的数据隔离出去,进一步减少传输。另外,长列表的每一项尽量用纯展示组件(不带业务逻辑),减少组件实例开销;列表项里的点击事件统一走事件委托,避免每个节点单独绑定监听。

五、踩坑清单

  • 行高不固定:内容长短不一导致虚拟滚动错位。要么固定行高,要么测量后缓存每行高度。
  • 滚动抖动:缓冲区和可视区切换时出现跳动。缓冲行数设够,且复用节点而非重建。
  • 图片风暴:滑动过程中疯狂请求图片。滑动中只保留当前批,节流加载。
  • setData 全量:一次更新全列表,性能打回原形。坚持按行更新。
  • 内存泄漏:列表销毁时定时器和图片请求未清理。onUnload 里统一清。
  • 通信过频:滚动事件高频触发 setData 调用。用节流合并,滚动监听只算索引,渲染分批更新。

六、工程落地建议

先量再优化:用小程序体验评分(如"性能"面板)看列表页的渲染耗时和内存,再决定是虚拟滚动、图片懒加载还是 setData 瘦身,通常三件事按"节点→图片→数据"顺序做。列表数据量在 50 条以内时不需要虚拟滚动,别过度设计。落地时建议把列表渲染拆成"可视区+缓冲区分批"两层,乔拓云轻应用的列表组件即按此思路设计,滚动性能用帧率面板持续监控验收。

七、复盘清单

  • 列表页帧率是否稳定在 30fps 以上?内存是否平稳?
  • 图片是否按需分批加载?滑动停止才拉取?
  • setData 是否按行更新?有无全量推送?
  • 渲染节点数是否控制在可视区加缓冲区范围内?

结语:长列表优化的本质是"少渲染、分批加载、按行更新",把这三件事做透,千条数据也能丝滑滚动。本文与《商城购物车并发合并怎么做:Redis 原子操作与本地暂存兜底》同属企业数字化落地避坑系列,可对照阅读。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、先明白卡顿的根源
  • 二、虚拟滚动:只渲染可视区
  • 三、增量渲染:分批出图不阻塞
  • 四、setData 瘦身:别把整个列表推给渲染层
  • 五、踩坑清单
  • 六、工程落地建议
  • 七、复盘清单
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档