虚拟列表-定高(Vue3)

如果后端返回一万条数据,你怎么展示?

方法一:打死后端

方法二:手动触底加载更多,或者定时器循环加载

方法三:虚拟列表

所谓虚拟列表,就是不一下子渲染所有的列表,而是只渲染用户看得见的,然后根据用户的滚动,将这个列表移动到可视区域,改变其内容。

这里介绍的是定高的虚拟列表,列表的每一项高度是固定的,下面是刚用vue3写的一个demo:

<template>
  <div ref="scroller" id="scroller">
    <div id="list" :style="{
      transform: `translateY(${translateY}px)`
    }">
      <Item v-for="item in list" :item="item"></Item>
    </div>
    <div :style="{
      height: holderHeight + 'px'
    }"></div>
  </div>
</template>

<script setup lang="ts">
import Item from './components/Item.vue';
import { computed, onMounted, reactive, ref, type ComputedRef } from 'vue';

let scroller = ref<HTMLElement | null>(null)

const itemHeight = 133
const len = 1000
const holderHeight = ref(len * itemHeight)
let gap = 4 + Math.floor(document.documentElement.clientHeight / itemHeight)
let scrollTop = ref(0)

const rawList = reactive(Array(len).fill('').map((_, i) => ({
  id: i,
  price: Math.random() * 1000
})))
let list = computed(_ => rawList.slice(startIndex.value, startIndex.value + gap))

let startIndex: ComputedRef<number> = computed(() => {
  if (scrollTop.value < itemHeight * 2) {
    return 0
  }
  return Math.ceil((scrollTop.value - itemHeight * 2) / itemHeight)
})

let translateY: ComputedRef<number> = computed(() => {
  return startIndex.value * itemHeight
})


onMounted(() => {
  scroller.value?.addEventListener('scroll', e => {
    scrollTop.value = (e.target as HTMLElement).scrollTop
  })
})
</script>

<style lang="scss">
* {
  padding: 0;
  margin: 0;
}

#scroller {
  height: 100vh;
  overflow: auto;
  position: relative;

  #list {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    will-change: transform;
  }
}
</style>

可以看到,一个固定高度的滚动元素,内部是一个用于撑开高度的空元素,以及关键的列表。列表根据高度计算出可以展示多少项,再前后追加两个缓冲。随着用户的滚动,动态计算初始索引及偏移。

定高的虚拟列表比较简单。对于不定高的虚拟列表大家可自行搜索,大致思路应该是给个默认值,比如有一百项,就创建一个长度为100的数组,填充这个默认值,一旦元素真正渲染,就获取高度替换掉对应的默认值,计算索引和偏移都是根据这个数组。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值