vue3加载大数据列表不卡顿解决方案

按照惯例:如何一次性加载30w条数据并且滚动不卡顿呢
直接上代码:

<template>
  <div>
    <div>{{list.length}}条数据</div>
    <div>{{startIndex}}-{{endIndex}}</div>
    <div class="wrap" :style="{'height':wrapHeight+'px'}" @scroll="scrollWrap" ref="refWrap">
      <div :style="{'height':(list.length*30).toString()+'px','position':'relative'}">
        <template v-for="(item,index) in listComputed" :key="index">
          <div class="list" :style="{'height':item.height+'px','top':'0px','transform':`translateY(${item.top}px)`}">
            <span>{{item.text}}</span>
          </div>
        </template>
      </div>

    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted, computed, reactive, Ref, onActivated } from 'vue'
import { ListItems } from "./interface/index"
export default defineComponent({
  name:"dynamicViews_three_index",
  setup(prop, context) {
    const list = reactive<ListItems[]>([])
    const wrapHeight = ref<number>(300)
    const items = ref<number>(300000)
    const refWrap = ref<any>(null)
    const scrollTop = ref<number>(0)
    const startIndex = ref<number>(0)
    const endIndex = ref<number>(0)
    // 显示的条数
    const visibleCount = computed<number>(() => {
      return Math.ceil(wrapHeight.value / 30)
    })
    const listComputed = computed(()=>{
      return list.slice(startIndex.value,Math.min(endIndex.value,list.length))
    })
    const scrollWrap = (e: any) => {
      scrollTop.value = e.srcElement.scrollTop
      showVisible(scrollTop)
    }
    const showVisible = (scrollTop:Ref):void=>{
      // 当前数据显示的索引
      startIndex.value = Math.floor(scrollTop.value / 30)
      endIndex.value = startIndex.value + visibleCount.value + 2
    }
    onMounted(() => {
      for (let i = 0; i < items.value; i++) {
        list.push({
          text: 'list_' + (i+1),
          height: 30,
          top: (30 * i).toString(),
        })
      }
      showVisible(scrollTop)
      console.log('mounted')
    })
    onActivated(()=>{
      if(scrollTop.value!==0){
        showVisible(scrollTop)
        refWrap.value.scrollTop = scrollTop.value
      }
    })
    return {
      list,
      items,
      refWrap,
      scrollWrap,
      wrapHeight,
      endIndex,
      startIndex,
      listComputed
    }
  },
})
</script>
<style scoped lang="scss">
.wrap {
  overflow: auto;
  position: relative;
  .list {
    position: absolute;
    width: 100%;
  }
}
</style>

讲解一下原理:
因为加载30w条数据,肯定一次性加载出来是会页面卡死的,那么就需要一次性只加载一部分,这个时候需要定好盒子的高度,并且定好内部展示列表的高度,css绝对定位去定位内容list的位置,通过js去计算每个item应该展示的位置,去获取滚动条滚动的距离,然后去计算顶部此时应该展示哪些数据,数据层分为一个渲染数据,一个原始数据,动态计算此时需要展示的数据索引,然后对原始数据进行截取

list.slice(startIndex.value,Math.min(endIndex.value,list.length))

展示效果
列表
列表2
dom
类似的,比如树形数据,按照这个思路,也可以做到加载大数据树,大数据树的后面再写
PS:自己改造改造vue2也能用

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值