你需要掌握的前端开发的高级功能---虚拟列表

前言

虚拟列表,最近听到这个概念,然后我做了下了解,果然是个好东西,当你面试的时候,如何优化后端返回的大量数据列表,如果你回答,做分页处理,嗯,这个也是不错的回答,然后面试官的你是中级水平,如果你回答,使用虚拟列表,恭喜你,你回答面试官心坎里了。你的级别也就能上一个台阶,当然,不能因为回答,一道面试题,就确定你级别,但是可以给面试官留下很好的印象,说不定你就是优先录取的对象。

定义

虚拟列表:其核心思想就是在处理用户滚动时,只改变列表在可视区域的渲染部分,然后使用padding或者translate来让渲染的列表偏移到可视区域中,给用户平滑滚动的感觉。

虚拟列表出现前的原因:
长列表渲染一直以来都是前端比较头疼的一个问题,如果想要在网页中放大量的列表项,纯渲染的话,对于浏览器性能将会是个极大的挑战,会造成滚动卡顿,整体体验非常不好,主要有以下问题:

  • 页面等待时间极长,白屏时间久,用户体验差
  • CPU计算能力不够,滑动会卡顿
  • GPU渲染能力不够,页面会跳屏
  • RAM内存容量不够,浏览器崩溃
  • 统的方法是使用懒加载的方式,下拉到底部获取新的内容加载进来,其实就相当于是在垂直方向上的分页叠加功能,(但随着加载数据越来越多,浏览器的回流和重绘的开销将会越来越大)

虚拟列表的原理

虚拟列表的核心步骤可以总结成五步:

  • 不把长列表数据一次性全部直接渲染在页面上
  • 截取长列表一部分数据用来填充可视区域;
  • 长列表数据不可视部分使用空白占位填充(下图中的startOffset和endOffset区域);
  • 监听滚动事件根据滚动位置动态改变可视列表
  • 监听滚动事件根据滚动位置动态改变空白填充

组件页面InfiniteScroll.vue

<template>
  <div ref="container" class="list-container" @scroll="hScroll">
    <div ref="content" class="list-content">
      <slot v-for="item in showList" :info="item" :key="item"></slot>
    </div>
  </div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
const container = ref(null)
const content = ref(null)
const props = defineProps(['list', 'itemHeight', 'showNum', 'start', 'end'])

const { list } = props

const itemHeight = ref(props.itemHeight)
const showNum = ref(list.length)
const start = ref(props.start)
const end = ref(props.end)
const initEnd = end.value
onMounted(() => {
  container.value.style.height = itemHeight.value * showlist.value.length + 'px'
  content.value.style.height = itemHeight.value * showNum.value + 'px'
})
const showList = computed(() => list.slice(start.value, end.value))
const hScroll = () => {
  const scrollTop = container.value.scrollTop

  start.value = Math.floor(scrollTop / itemHeight.value)
  end.value = start.value + initend
  if (end.value >= showNum.value) {

    start.value = showNum.value - initend
    end.value = showNum.value
  }
  content.value.style.transform = `translateY(${start, value * itemHeight.value}px)`
  content.value.style.height = (itemHeight.value * showNum, value) - (start.value *
    itemHeight.value) + 'px'
}
</script>
<style lang="less" scoped>
.list-container {
  width: 400px;
  overflow-y: scroll;
}
</style>

使用组件InfiniteScroll的父级页面

<template>
  <div>
  <InfiniteScroll
  itemHeight="21"
  start="1"
  end="16"
  :list="list">
  <template v-slot="{ info }">
  <p>{{ info }}</p>
  </template>
  </InfiniteScroll>
  </div>
  </template>
  <script setup>
  import { ref } from 'vue';
  import InfiniteScroll from "./InfiniteScroll.vue"
  const list =ref(['你好1','你好2','你好3','你好4','你好5','你好6','你好7','你好8','你好9','你好10','你好11','你好12','你好13','你好14','你好15','你好16','你好17','你好18','你好19','你好20','你好21','你好22','你好23','你好24'])
</script>
<style>

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值