0


H5移动端 Vue3 + vue-virtual-scroller 实现长列表性能优化

文章目录

移动端在渲染长列表时 大量dom节点的渲染和重绘重排会导致页面卡顿、滚动不流畅、设备耗电加快、影响移动设备电池寿命等性能问题

这里分享使用【虚拟滚动】方案进行长列表优化,以Vue3为例,推荐使用

vue-virtual-scroller

先列举

vue-virtual-scroller

相关官方文档帮助学习

  • 官方文档
  • Live demo
  • Live demo 源码
  • Video demo

安装 vue-virtual-scroller

npminstall--save vue-virtual-scroller@next
yarnadd vue-virtual-scroller@next

引入

安装所有组件:

import VueVirtualScroller from'vue-virtual-scroller'

app.use(VueVirtualScroller)

按需引入组件:

import{ RecycleScroller }from'vue-virtual-scroller'

app.component('RecycleScroller', RecycleScroller)

引入样式文件

import'vue-virtual-scroller/dist/vue-virtual-scroller.css'

📢注意事项

  1. 整个列表的高度要写死,不然会将整改列表作为可视区域,会出现渲染全部数据而不是只渲染可视区域的问题; 这里推荐使用 flex: 1; 实现,比 height: calc(100vh - 30vw); 更优雅、更易维护
  2. 使用 -webkit-overflow-scrolling: touch; 开启硬件加速,ios高版本自带
  3. 使用 overscroll-behavior: none; 禁用iOS回弹效果

使用

使用

DynamicScroller

组件渲染不确定高度的组件

基础使用

<divclass="content-wrap"><DynamicScroller:items="dataList":min-item-size="160"key-field="id"class="virtual-scroller"><template#default="{ item, index, active }"><DynamicScrollerItem:item="item":active="active":size-dependencies="[item.status, item.type]":data-index="index"class="virtual-scroller-item"><!-- 渲染组件 --><TaskItem:data="item"/></DynamicScrollerItem></template></DynamicScroller></div>
.icc__container{height: 100vh;display: flex;flex-direction: column;box-sizing: border-box;.icc__content-wrap{flex: 1;.virtual-scroller{/* 开启硬件加速 -webkit-overflow-scrolling: touch; ios高版本自带 */-webkit-overflow-scrolling: touch;/* 禁用回弹效果 */overscroll-behavior: none;height: 100%;}}}

上拉加载

vant List

+

DynamicScroller

会导致连续触发

vant List

load 事件,所以只能手写上拉加载

  1. 监听 DynamicScroller 滚动事件,如果当前距离顶部的值加上可视区域的值大于等于总高度,则滚动条触底,加载更多
  2. 使用 DynamicScroller``````after 插槽,定义加载中、加载完成、加载失败等状态
<divclass="content-wrap"><DynamicScroller:items="dataList":min-item-size="160"key-field="id"class="virtual-scroller"@scroll="handleDynamicScrollerScroll"><template#default="{ item, index, active }"><DynamicScrollerItem:item="item":active="active":size-dependencies="[item.status, item.type]":data-index="index"class="virtual-scroller-item"><!-- 渲染组件 --><TaskItem:data="item"/></DynamicScrollerItem></template><template#after><divclass="after"><van-loadingv-show="loadMoreLoading">加载中...</van-loading><spanv-show="finished">没有更多了</span><spanv-show="loadError && !loadMoreLoading"@click="handleLoadMore">请求失败,点击重新加载</span></div></template></DynamicScroller></div>
// 上拉loadingconst loadMoreLoading = ref<boolean>(false)// 没有更多数据了const finished = ref<boolean>(false)// 加载失败const loadError = ref<boolean>(false)// 实现上拉加载consthandleDynamicScrollerScroll=(e: Event)=>{// 距顶部const scrollTop =(e.target as HTMLDivElement)?.scrollTop ||0// 可视区高度const clientHeight =(e.target as HTMLDivElement).clientHeight ||0// 滚动条总高度const scrollHeight =(e.target as HTMLDivElement)?.scrollHeight ||0// 触底距离const offset =300// 如果当前距离顶部的值加上可视区域的值大于等于总高度,则滚动条触底if(scrollTop + clientHeight >= scrollHeight - offset){if(!loadMoreLoading.value &&!finished.value &&!loadError.value){
      console.log('滚动到底部了')
      loadMoreLoading.value =truehandleLoadMore()}}}

下拉刷新

使用

vant PullRefresh

实现下拉刷新

如果直接用

vant PullRefresh

包裹虚拟滚动,会导致无法向下滑动,任何位置下拉都会触发下拉刷新。

解决方案:

1. `vant PullRefresh` 中有 `disabled`  选项,可以禁用下拉刷新,默认设置为 `false`
2. 监听滚动条滚动事件中的 `scrollTop`,
3. 如果 `scrollTop` 小于4,则将 `disabled` 变为 `false`
4. 否则将 `disabled` 变为 `true`
<template><divclass="container"><van-pull-refreshv-model="refreshLoading"@refresh="handlerefresh":disabled="disabledPullRefresh"class="content-wrap"><templatev-if="dataList.length > 0"><DynamicScroller:items="dataList":min-item-size="160"key-field="id"class="virtual-scroller"id="virtual-scroller"@scroll="handleDynamicScrollerScroll"><template#default="{ item, index, active }"><DynamicScrollerItem:item="item":active="active":size-dependencies="[item.status, item.type]":data-index="index"class="virtual-scroller-item"><!-- 渲染组件 --><TaskItem:data="item"/></DynamicScrollerItem></template><template#after><divclass="after"><van-loadingv-show="loadMoreLoading">加载中...</van-loading><spanv-show="finished">没有更多了</span><spanv-show="loadError"@click="handleLoadMore">请求失败,点击重新加载</span></div></template></DynamicScroller></template><van-emptyv-elseimage="./no_data.png"description="暂无匹配数据":image-size="['60vw', 'auto']"class="h-80vh"/></van-pull-refresh></div><van-back-toptarget="#virtual-scroller"/></template>
// 下拉loadingconst refreshLoading = ref<boolean>(false)// 禁用下拉刷新const disabledPullRefresh =ref(false)// 上拉loadingconst loadMoreLoading = ref<boolean>(false)// 没有更多数据了const finished = ref<boolean>(false)// 加载失败const loadError = ref<boolean>(false)// 实现上拉加载consthandleDynamicScrollerScroll=(e: Event)=>{// 距顶部const scrollTop =(e.target as HTMLDivElement)?.scrollTop ||0// 可视区高度const clientHeight =(e.target as HTMLDivElement).clientHeight
  // 滚动条总高度const scrollHeight =(e.target as HTMLDivElement)?.scrollHeight
  const offset =300// 如果直接用 `vant PullRefresh` 包裹虚拟滚动,会导致无法向下滑动,任何位置下拉都会触发下拉刷新。// 控制是否开启下拉刷新if(scrollTop <=4){
    disabledPullRefresh.value =false}else{
    disabledPullRefresh.value =true}// 如果当前距离顶部的值加上可视区域的值大于等于总高度,则滚动条触底if(scrollTop + clientHeight >= scrollHeight - offset){if(!loadMoreLoading.value &&!finished.value &&!loadError.value){
      console.log('滚动到底部了')
      loadMoreLoading.value =truehandleLoadMore()}}}

兄弟们,上面的代码在项目中踩坑实测过了!!

源码就不贴了😄


本文转载自: https://blog.csdn.net/qq_41887214/article/details/137249989
版权归原作者 __畫戟__ 所有, 如有侵权,请联系我们删除。

“H5移动端 Vue3 + vue-virtual-scroller 实现长列表性能优化”的评论:

还没有评论