美文网首页
vue 实现简单虚拟列表

vue 实现简单虚拟列表

作者: wxw_威 | 来源:发表于2023-08-07 15:18 被阅读0次

当后端一次性返回10w条数据,前端页面如果一次渲染的话,会有延迟,或者页面直接卡死,所以需要用到虚拟列表,每次加载可视区域内的数据,滚动页面的时候,更新数据。
废话不多说,直接上代码~
像这样,只更新可视区域的数据:


1691479026988.png

1、cell高度固定

<template>
  <div class="base-layout">
    <div ref="scrollRef" class="scroll-view" @scroll="handleScroll">
      <div class="scroll-content" :style="{ height: contentHeight + 'px' }">
        <div class="content-list" :style="{ paddingTop: topValue + 'px' }">
          <p v-for="item in list" :key="item.id">{{ item.id }}</p>
        </div>
      </div>
    </div>
  </div>
</template> 
<script lang="ts" setup>
  import { computed, onMounted, reactive, ref } from 'vue';
  
  let allList = ref(<any>[])  // 所有数据
  let contentHeight = ref(0)  // 根据数据,计算scrolleViwe 的内部区域高度,为了显示滚动的可视区域
  let topValue = ref(0) // 滚动条滚动距离顶部的高度
  let startIndex = ref(0) // 要截取所有数据的起始下标
  let visibleCount = ref(0)  // 可视区域内的cell数量
  const itemHeight = ref(30)  // cell 的高度
  const scrollRef = ref()

  // 可视区域内要显示的数组
  let list = computed(() => {
    let arr = allList.value.slice(startIndex.value, startIndex.value + visibleCount.value)
    return arr
  })

  onMounted(() => {
    // scrollRef.value.offsetHeight: 获取可视窗口的高度
    // 根据cell固定高度,计算可视区域内cell的数量
    visibleCount.value = Math.ceil(scrollRef.value.offsetHeight / itemHeight.value)

    getAllList()
  })

  function getAllList() {
    for(let i = 1; i <= 100000; i++) {
      allList.value.push({ id: i })
    }
    // 计算内容区域高度
    contentHeight.value = allList.value.length * 30
  }
  function handleScroll(val: { target: { scrollTop: number; }; }) {
    // 获取滚动条距离顶部的距离
    topValue.value = val.target.scrollTop
    // 计算起始下标
    startIndex.value = Math.floor(topValue.value / itemHeight.value) 
  }

</script>

<style lang="scss" scoped>
.base-layout {
  padding: 8px 20px;
  .scroll-view {
    background-color: papayawhip;
    border: 1px solid orange;
    box-sizing: border-box;
    height: 300px;
    width: 300px;
    overflow-y: auto;
  }
  p {
    height: 30px;
    line-height: 30px;
    margin: 0;
    border-bottom: 1px solid gainsboro;
    box-sizing: border-box;
  }
}
</style>

相关文章

网友评论

      本文标题:vue 实现简单虚拟列表

      本文链接:https://www.haomeiwen.com/subject/zzegpdtx.html