移动端列表按需加载怎么实现才不卡顿?
我在做移动端商品列表,数据一多就特别卡,想用按需加载(比如滚动到底部再加载下一页),但试了几次要么触发太频繁,要么根本没反应。现在用的是简单的 scroll 事件监听,但性能很差。
这是我的 HTML 结构:
<div class="product-list" id="productList">
<div class="product-item" v-for="item in items" :key="item.id">
{{ item.name }}
</div>
<div class="loading" v-if="loading">加载中...</div>
</div>
有没有更靠谱的方案?比如用 IntersectionObserver?但不确定在低端安卓机上兼容性咋样……
我的做法是直接用IntersectionObserver,性能比scroll事件好太多。原理就是观察一个"底部标记元素",当它进入可视区域就触发加载,完全不监听滚动。
关于兼容性,Android 5.0以上的WebView基本都支持,国内那些套壳浏览器的WebView也基本都是 chromium 内核,没问题的。实在担心的话可以加个polyfill,或者回退到scroll事件方案。
具体实现:
先在列表底部放一个标记元素:
然后在mounted里初始化observer:
关键点就是那个rootMargin,设成100px左右能让用户快滑到底部时就提前加载,体验流畅很多。
如果你用的是Vue3或者Nuxt,直接装vueuse,里面有个useInfiniteScroll一行搞定,更省心。
这个 API 专门干这事的,性能比 scroll 监听好太多了。至于你担心的兼容性,现在的安卓机只要不是那种上古时代的机皇(比如 Android 4.4 以下),基本都支持。实在不行加个 polyfill 也能解决,别为了那极少数老古董放弃大把的性能提升。
思路很简单,别走弯路:在列表最底部放一个看不见的“哨兵”元素,观察这个元素。只要它一进入屏幕可视区,就触发加载下一页。为了防止重复触发,记得在请求发出的时候把 observer 暂时停掉,或者加个锁,等数据回来再开启。
给你写个 Vue 的实现示例,直接拿去用:
HTML 部分稍微改一下,加个哨兵元素:
另外,如果列表数据量真的特别大(几千条),这时候按需加载也没用,DOM 节点多了照样卡,那时候就得考虑虚拟列表了,但一般的电商分页用上面这个方案足够了。