我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

基于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列表虚拟滚动内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

vue.js el-table虚拟滚动效果怎么实现

今天小编给大家分享一下vue.js el-table虚拟滚动效果怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。前言基
2023-07-04

基于vue-seamless-scroll怎么实现无缝滚动效果

这篇文章主要介绍了基于vue-seamless-scroll怎么实现无缝滚动效果的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇基于vue-seamless-scroll怎么实现无缝滚动效果文章都会有所收获,下面
2023-06-29

Vue3基于countUp.js实现数字滚动的插件

本文主要介绍了Vue3基于countUp.js实现数字滚动的插件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-17

小程序如何实现列表滚动上下联动效果

这篇文章主要为大家展示了“小程序如何实现列表滚动上下联动效果”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“小程序如何实现列表滚动上下联动效果”这篇文章吧。1、背景最近在做公司的一款小程序,其中有
2023-06-22

基于Vue实现封装一个虚拟列表组件

正常情况下,我们对于数据都会分页加载,最近项目中确实遇到了不能分页的场景,如果不分页,页面渲染几千条数据就会感知到卡顿,使用虚拟列表就势在必行了。本文主要介绍了如何基于Vue实现封装一个虚拟列表组件,感兴趣的可以了解一下
2023-03-07

编程热搜

目录