专注小程序 / APP 开发,用代码改变生活

获取方案
全国分站 主站首页 北京分站 石家庄分站 唐山分站 保定分站 廊坊分站 沧州分站 郑州分站 邯郸分站

小程序开发实录:一个列表页的优化过程

小程序开发 2026-11-01 0 阅读 0 点赞 原创

上周把手上一个社区团购小程序的商品列表页重做了一遍。这个页面从上线起就有点慢,用户滑到第三屏开始掉帧,运营那边也反馈说加载时白屏时间长。我本来以为是小问题,结果一查数据,这个页面的跳出率比首页高了快一倍。这次优化前后折腾了三天,记录一下过程,给遇到类似情况的朋友参考。

小程序开发实录:一个列表页的优化过程

先别急着改代码,先量一下

我的习惯是动手前先拿数据。微信开发者工具的性能面板和真机调试都用上了,重点看两个东西:一是首屏渲染耗时,二是滚动时的 setData 频率。结果不太好看:

  • 首屏从 onLoad 到列表可见,平均 1.8 秒,低端机超过 3 秒
  • 一次滚动触底加载 20 条数据,setData 传了整个数组
  • 列表项里有个倒计时组件,每个 item 各自跑一个 setInterval

问题基本清楚了:数据量不大,但传递方式太粗暴,加上定时器滥用,逻辑层和渲染层之间的通信被拖垮了。

第一刀:setData 只传增量

原来分页加载的写法是这样的,每次把整个列表重新 set 一遍:

// 优化前
onReachBottom() {
  this.page++
  fetchList(this.page).then(res => {
    this.setData({
      list: this.data.list.concat(res.data)
    })
  })
}

数据到 100 条以后,每次 setData 都在传一个几百 KB 的对象,序列化和跨线程传输的开销很吓人。改成用路径更新,只传新增的那一段:

// 优化后
onReachBottom() {
  this.page++
  fetchList(this.page).then(res => {
    const start = this.data.list.length
    const patch = {}
    res.data.forEach((item, i) => {
      patch[`list[${start + i}]`] = item
    })
    this.setData(patch)
  })
}

就这一处改动,滚动加载的卡顿感基本消失了。原理不复杂,setData 的数据量直接决定通信耗时,能少传就少传。

第二刀:干掉列表里的定时器

每个商品卡片有个“距结束还剩 xx:xx”的倒计时。之前的实现是每个组件在 attached 里起一个 setInterval,一屏十几个组件就是十几个定时器,而且每秒钟每个定时器都触发一次 setData。

改成页面级统一维护一个定时器,每秒只更新一次,并且只更新变化了的那几条:

// 页面里统一 tick
startTick() {
  this.timer = setInterval(() => {
    const now = Date.now()
    const patch = {}
    this.data.list.forEach((item, i) => {
      if (item.endTime > now) {
        patch[`list[${i}].countdown`] = formatLeft(item.endTime - now)
      }
    })
    if (Object.keys(patch).length) this.setData(patch)
  }, 1000)
}

组件只负责展示,不再自己管时间。页面 onHide 和 onUnload 里记得 clearInterval,这个坑我踩过,切后台没清定时器,回来以后定时器叠了好几层。

第三刀:图片和骨架屏

列表图之前直接用的原图,一张 200KB 起步。后来让后端在 CDN 上开了缩放参数,列表里统一取 300px 宽的缩略图,配合 lazy-load,首屏图片流量降了七成多。

白屏的问题用骨架屏解决。不是上第三方库,就是页面初始 data 里放一个长度为 6 的占位数组,渲染灰色块,真实数据回来再替换。代码很少,但体感提升明显,用户至少知道页面在加载,不会以为卡死了。

改完后的数据

  • 首屏可见时间从 1.8 秒降到 0.9 秒左右,低端机 1.5 秒内
  • 滚动掉帧基本没有了,开发者工具里 FPS 稳定在 50 以上
  • 页面跳出率降了大概 20%,这个有运营数据佐证

说点题外话。这次优化没用什么高深技术,全是基础操作,但效果比我想的明显。我见过不少项目一上来就想着上分包、上预加载,结果连 setData 都在传全量数据。性能优化这事儿,先量再改,别凭感觉。另外,真机测试一定要用中低端安卓机,开发者工具和 iPhone 上的表现会骗人。

这个项目后面还打算把列表虚拟化做一下,长列表场景下 DOM 节点太多还是会有压力。有进展再写一篇。

小程序开发踩坑三年,我总结了这5条邯郸做小程序,别急着写代码

评论 (0)

还没有评论,快来抢沙发吧~

好想法,值得被认真交付

从小程序、APP 到全栈网站,一站式把想法变成可落地的产品

微信咨询

微信扫码,直接沟通需求