基于Vue3实现列表虚拟滚动效果

 更新时间:2022年04月15日 10:11:35   作者:yellowhomecar  
这篇文章主要为大家介绍了如何利用Vue3实现列表虚拟滚动效果,文中的示例代码讲解详细,对我们学习或工作有一定价值,需要的可以参考一下

前言

近期在做一个网页播放器项目中,用到很多需要展示歌单的列表

一个歌单动辄千百首歌曲,页面中的元素太多导致热重载的时候 chrome 直接崩了 😢

于是无限滚动列表提上日程

写的有点乱,也是第一次用 typescript 写项目,先记录一下

完成效果

思路和需要解决的问题

与懒加载不同,虚拟滚动需要一次性获取所有数据,但是只显示屏幕可见范围内的数据

要做到这些我需要知道:

  • 一行的高度
  • 屏幕范围内能显示的行数
  • 列表在页面中距离网页顶部的位置
  • 滚动条高度

假设满屏能容纳 10 条数据,需要加载的数据是一个数组listData,只需要裁剪数据范围listData.slice(0, 10)

随着滚动条向下,将滚动条高度/一行的高度可以计算出当前行数

而要模拟滚动条高度就要在页面挂载时就手动设置页面的高度一行高度*listData.length

最后也是最关键的是保持列表一直保持在当前位置上,手动设置列表容器padding-top等于当前滚动条高度

有一个仍未解决的问题,就是每次来回滚动歌曲封面都要重新请求 😮

vue3+setup 写的组件

<script lang="ts" setup>
import { ref, computed, nextTick, reactive, watchEffect, onUnmounted } from 'vue'

const props = defineProps<{
  listData: Array<any>
}>()

// 列表HTMLElementDom
const ulRef = ref<any>(null)

// 屏幕高度
const screenH = document.documentElement.clientHeight

const data = reactive<any>({
  // 列表第一项的高度(起始高度)
  initH: 0,

  // 一行的高度
  unitH: 0,

  // 屏幕范围内能显示个数
  displayCount: 1,

  // 列表起始值
  startIdx: 0
})

const listData = computed(() => {
  let endIdx = data.startIdx + data.displayCount
  if (endIdx >= props.listData.length) endIdx = props.listData.length

  return props.listData.slice(data.startIdx, endIdx).map((v, k) => {
    v.idx = data.startIdx + k + 1
    return v
  })
})

function scrollHandler() {
  // 当前滚动高度
  const curScrollTop = document.documentElement.scrollTop
  if (curScrollTop > data.initH) {
    const addCount = Math.floor((curScrollTop - data.initH) / data.unitH)
    ulRef.value.style.setProperty('padding-top', `${addCount * data.unitH}px`)
    data.startIdx = addCount
  } else {
    ulRef.value.style.setProperty('padding-top', '0px')
    data.startIdx = 0
  }
}

watchEffect(() => {
  if (props.listData.length > 0) {
    nextTick(() => {
      // 列表距离顶部距离
      data.initH = ulRef.value.getBoundingClientRect().top + document.documentElement.scrollTop
      // 计算每行高度
      data.unitH = ulRef.value.children[0].offsetHeight
      // 计算屏幕内能显示的行数
      data.displayCount = Math.ceil(screenH / data.unitH)
      // 设置列表总高度 = 一行高度 * 行数
      const listH = data.unitH * props.listData.length
      ulRef.value.style.setProperty('height', `${listH}px`)

      window.removeEventListener('scroll', scrollHandler)
      window.addEventListener('scroll', scrollHandler)
    })
  }
})

onUnmounted(() => {
  window.removeEventListener('scroll', scrollHandler)
})
</script>

<template>
  <ul ref="ulRef">
    <li v-for="(listItem, listIndex) in listData" :key="`list-${listIndex}`" :data-idx="listItem.idx">
      <slot :listItem="listItem"></slot>
    </li>
  </ul>
</template>

使用组件

<script lang="ts" setup>
import InfiniteList from './InfiniteList.vue'

const songs = [] // 列表数据
</script>

<template>
  <infinite-list :listData="songs">
    <template #default="{ listItem }">
      <div>{{ listItem.title }}</div>
      <!-- ... -->
    </template>
  </infinite-list>
</template>

到此这篇关于基于Vue3实现列表虚拟滚动效果的文章就介绍到这了,更多相关Vue列表虚拟滚动内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Element+vue实现开始与结束时间限制

    使用Element+vue实现开始与结束时间限制

    这篇文章主要为大家详细介绍了使用Element+vue实现开始与结束时间限制,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 解决vue props传Array/Object类型值,子组件报错的情况

    解决vue props传Array/Object类型值,子组件报错的情况

    这篇文章主要介绍了解决vue props传Array/Object类型值,子组件报错的情况,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • vue 实现微信浮标效果

    vue 实现微信浮标效果

    微信的浮窗,大伙应该都用过,当我们正在阅读一篇公众号文章时,突然需要处理微信消息,点击浮窗,在微信上会有个浮标,点击浮标可以再次回到文章。今天小编抽空给大家介绍vue 实现微信浮标效果,感兴趣的朋友一起看看吧
    2019-09-09
  • Vue js with语句原理及用法解析

    Vue js with语句原理及用法解析

    这篇文章主要介绍了Vue js with语句原理及用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • vue-cli3在main.js中console.log()会报错的解决

    vue-cli3在main.js中console.log()会报错的解决

    这篇文章主要介绍了vue-cli3在main.js中console.log()会报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • vue.js通过自定义指令实现数据拉取更新的实现方法

    vue.js通过自定义指令实现数据拉取更新的实现方法

    数据拉取更新这个功能相信大家基本都见过,但是如果要做起来却不止如何做起,所以这篇文章给大家分享了vue.js通过自定义指令实现的方法,阅读本文需要对vue有一定理解,有需要的朋友们下面来一起看看吧。
    2016-10-10
  • 通过vue-cli3构建一个SSR应用程序的方法

    通过vue-cli3构建一个SSR应用程序的方法

    这篇文章主要介绍了通过vue-cli3构建一个SSR应用程序,以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
    2018-09-09
  • 阿望教你用vue写扫雷小游戏

    阿望教你用vue写扫雷小游戏

    这篇文章主要介绍了阿望教你用vue写扫雷小游戏,本文通过实例代码效果图展示的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-01-01
  • Vue渲染流程步骤详解

    Vue渲染流程步骤详解

    在Vue里渲染一块内容,会有四个流程步骤,那么该怎么理解这个流程呢,所以本文就给大家详细讲解一下Vue 渲染流程,文中有纤细的代码示例供大家参考,需要的朋友可以参考下
    2023-07-07
  • vue通过v-show实现回到顶部top效果

    vue通过v-show实现回到顶部top效果

    这篇文章主要介绍了vue通过v-show实现回到顶部top效果,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12

最新评论