vue 虚拟列表滚动

需求来了

项目中有一个移动端的长列表,考虑再三,决定用虚拟列表优化一下,关于虚拟列表的实现网上有挺多方案的,为了省时省力还是决定采用成熟的第三方库,于是开始 github 之旅~
搜索关键字 vue virtual ,选取前两个 star hin 高的项目,展开看看对比对比看看哪个符合我的要求~是我的 the one~

对比之 vue-virtual-scroller

地址

[https://github.com/Akryum/vue-virtual-scroller] star: 6.2k

demo 地址

用法

  <RecycleScroller
    class="scroller"
    :items="list"
    :item-size="32"
    key-field="id"
    v-slot="{ item }"
  >
    <div class="user">
      {{ item.name }}
    </div>
  </RecycleScroller>

注意事项:

  • 官网的 demo 只提供了一次性加载大量数据的案例,并且亲测,如果自己定义无限加载的方法话,向上滚动会出现白屏。

对比之 vue-virtual-scroll-list

地址

[https://github.com/tangbc/vue-virtual-scroll-list] star: 3.1k

demo 地址

[https://tangbc.github.io/vue-virtual-scroll-list/#/]

用法

<virtual-list style="height: 360px; overflow-y: auto;" // make list scrollable
      :data-key="'uid'"
      :data-sources="items"
      :data-component="itemComponent"
    />

注意事项

  • 列表项需要以组件的方式传入
  • 如果需要用原生页面的滚动事件,比如列表+上方固定栏的布局,可以开启 :page-mode="true",取消 scroller 的样式,原生。

对比结果:

经过对比最终决定使用 vue-virtual-scroll-list ,因为它在官方的 demo 中给出了无限加载的例子,且实测运行良好。而vue-virtual-scroller 则更适合用于前端分页加载大量数据的例子。

使用方式:

下面是基于 vue3 composition api 进行的封装,方便复用,如果是 vue2 的项目, 安装 @vue/composition-api 插件就可以毫无阻碍的使用 composition-api 啦!亲测没问题。

  • 安装 npm i vue-virtual-scroll-list --save

  • main.ts 全局注册组件

// 全局注册 虚拟滚动的组件
import VirtualList from 'vue-virtual-scroll-list'
Vue.component('virtual-list', VirtualList)
  • 封装公共逻辑 useVirtualInfinite.ts
import { ref, onMounted, Ref } from 'vue'

declare type returnType = {
  loading: Ref<boolean>
  onScrollToBottom: () => void
  list: Ref<any[]>
}
export default function useVirtualInfinite (getListFn: ()=>Promise<any>) : returnType {
  const loading = ref(false)
  const list = ref<any[]>([])
  const onScrollToBottom = () => {
    getData()
  }

  // 获取数据方法
  const getData = async () => {
    if (!loading.value) {
      loading.value = true
      const { data } = await getListFn()
      // eslint-disable-next-line
      data.rows.forEach((item: any) => (item.id = new Date().getTime()));
      list.value.push(...data.rows)
      loading.value = false
    }
  }

  // 挂载之后 获取 data
  onMounted(() => {
    getData()
  })

  return {
    onScrollToBottom,
    loading,
    list
  }
}
  • 愉快使用
<template>
  <virtual-list
    :data-key="'id'"
    :data-sources="list"
    :data-component="commentItem"
    :page-mode="true"
    v-on:tobottom="onScrollToBottom"
  >
    <div slot="footer" class="loading-spinner text-center">加载中...</div>
  </virtual-list>
</template>

<script>
const { list, onScrollToBottom } = useVirtualInfinite(getList)
return {
    list,
    onScrollToBottom
}
</script>
posted @ 2021-10-26 15:01  下小朋友  阅读(4399)  评论(0编辑  收藏  举报