当前位置:   article > 正文

笔记: 移动端h5 vue3+vue-virtual-scroller加载不定高巨量数据,支持上拉加载,下拉刷新(配合vant PullRefresh)+ 分页加载以及避坑指南_vue-virtual-scroll-list select 下拉分页

vue-virtual-scroll-list select 下拉分页

废话(不是): 项目是一个移动端的社区,可以发帖,可发布文字+图片(最多9张),之前直接搭的页面,通过分页加载数据,一次请求10条。后来产品那边反映在ios端会出现发热严重和掉电的情况。(部分原因: 社区首页是一直有兜底数据的,一直滑虽然分页,但dom会越堆越多。还有可能是定时器和监听器没关闭)问了下领导知道有"虚拟滚动/虚拟列表"这么个东西,网上找了几个成熟的库。

vue2:

  1. tangbc/vue-virtual-scroll-list
  2. Taro virtualscroll (组件库里的组件)
  3. Akryum / vue-virtual-scroller

vue3:

  1. reactjser / vue3-virtual-scroll-list (Forked from vue2 vue-virtual-scroll-list )
  2. tnfe / vue3-infinite-list
  3. Akryum / vue-virtual-scroller

项目结构

v-for(item, index) 渲染的dom,循环在父组件,子组件很多逻辑过度依赖循环的item,index,并且子组件Item高度完全不可控。自己造轮子失败,无法确定准确高度,想不通rem怎么动态设置。不知道该如何抽离子组件, Item多页面复用
要虚拟滚动的结构
搜遍全网,这几个基本不适合我这个情况: vue3-virtual-scroll-list 子组件以函数形式传入,无法监听prop和emit事件,官方issue有人提过这个问题,作者建议通过eventBus等其他方式交互,Taro virtualscroll 支持index,并且支持插槽,可以正常写子组件,事件交互都不受影响,但是它的动态高度是写死的 比如官方的例子: getItemSize 是一个有如下语法的函数 : (i: number): number, 通过这个函数可以动态设置元素宽高.

 const getItemSize = (i: number): number => {
      switch (i % 4) {
        case 1:
          return 80;
        case 2:
          return 50;
        case 3:
          return 100;
        default:
          return 200;
      }
    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

官方也在git上给予我答复
在这里插入图片描述
只能放弃,最后用 Akryum / vue-virtual-scroller 的库基本实现需求。

Akryum / vue-virtual-scroller 的坑

如果是ios端H5,在这个库上滑/下滑滚动的时候,屏幕会闪动,并且严重的时候会中断滑动。Android/pc正常,很丝滑。

ios端h5解决方案/避雷:

  1. 浏览issue发现,降低版本可解决问题。我降到了2.0.0-beta.3
  2. 高度一定写死。不能用transform或者动画改变高度的值。不然闪动非常严重
  3. 开启硬件加速 -webkit-overflow-scrolling: touch; ios高版本自带

使用方法:

  1. 安装组件库 (上述问题降低版本至beta4以下)
npm install --save vue-virtual-scroller@next 
  • 1
  1. 全局引入/按需引入
//Install all the components:

import VueVirtualScroller from 'vue-virtual-scroller'

app.use(VueVirtualScroller)

//Use specific components:

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

app.component('RecycleScroller', RecycleScroller)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 引入组件并设置固定高度
 <DynamicScroller
    :items="items"
    :min-item-size="54"
    class="scroller"
  >
    <template v-slot="{ item, index, active }">
      <DynamicScrollerItem
        :item="item"
        :active="active"
        :size-dependencies="[
          item.message,
        ]"
        :data-index="index"
      >
        <div class="avatar">
          <img
            :src="item.avatar"
            :key="item.avatar"
            alt="avatar"
            class="image"
          >
        </div>
        <div class="text">{{ item.message }}</div>
      </DynamicScrollerItem>
    </template>
  </DynamicScroller>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
.scroller {
height: calc(100vh - 160px);
-webkit-overflow-scrolling: touch;
}
  • 1
  • 2
  • 3
  • 4
  1. 实现上拉加载 + loading图标(vant)
    通过给虚拟滚动设置固定id,添加scroll监听
<DynamicScroller
    :items="items"
    :min-item-size="54"
    class="scroller"
    id="virtualScroller"
  >
  ...
  </DynamicScroller>


 let virtualScroller = document.getElementById('virtualScroller')
 virtualScroller ? virtualScroller.addEventListener('scroll', handleScroller) : ''
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

监听事件中判断是否触底 因为是移动端 用 scrollTop + clientHeight + 1 >= scrollHeight判断

const handleScroller = (e) => {
  if (scrollTop + clientHeight + 1 >= scrollHeight) {
   // virtualScrollerAllow.value = true // 触底逻辑
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5

ios触底会回弹,导致疯狂触发触底的逻辑,建议用一个单独变量控制是否到底,再watch监听这个变量,true/false 来判断是否执行触底逻辑 (可能影响性能)

加入 “加载中/加载失败/到底文案及图标”,vant中list组件 虚拟滚动完算是废了

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/97428
推荐阅读
相关标签