欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Vue如何手寫一個虛擬列表

 更新時間:2024年04月19日 10:22:03   作者:吃肉不吃皮  
虛擬列表是一種優(yōu)化長列表渲染的技術(shù),它可以在保持流暢性的同時,渲染大量的數(shù)據(jù),本文主要介紹了如何使用vue手寫一個虛擬列表,感興趣的可以了解下

前言

何為虛擬列表?

回答這個問題先想一下,對于返回的幾千上萬條列表數(shù)據(jù),作為前端會如何渲染?

分頁唄,最開始想到的就是分頁。但是,萬一接口沒做分頁呢?好,就算后端做分頁了,那么用戶在瀏覽到第幾千條、第幾萬條數(shù)據(jù)時前端難道要把這第幾千條、幾萬條的DOM都渲染出來嗎?顯然是很消耗性能的(畢竟如此多的DOM,而且每個DOM內(nèi)部都有其他樣式細(xì)節(jié))如何優(yōu)化?此時就可以用到虛擬列表了

虛擬列表是一種優(yōu)化長列表渲染的技術(shù),它可以在保持流暢性的同時,渲染大量的數(shù)據(jù)。

在傳統(tǒng)的列表渲染中,如果列表非常長,會導(dǎo)致渲染時間過長(前面所說的會有幾千幾萬個DOM),頁面卡頓,用戶體驗變得非常差。而虛擬列表則是只渲染可見區(qū)域內(nèi)的數(shù)據(jù),而非全部渲染,這樣就可以大大提高渲染效率,保持頁面流暢性

常見場景

商品列表、社交列表...(暫時想到這兩個)

手寫虛擬列表

進行虛擬列表的實現(xiàn)之前先搞清楚一個問題:

是什么造成了這么多數(shù)據(jù)在渲染時產(chǎn)生卡頓?是數(shù)據(jù)數(shù)量太多引起的嗎?

準(zhǔn)確來說,應(yīng)該是是由于要渲染的DOM太多造成的卡頓。數(shù)據(jù)本身只是數(shù)據(jù),對于拿到的幾千上萬條數(shù)據(jù)它本身的大小對于內(nèi)存來說只能說是冰山一角吧

虛擬列表的原理

數(shù)據(jù)我還是這么多數(shù)據(jù),但是我不一次性渲染這么多數(shù)據(jù),我只渲染其中的一小部分(比如十條),這樣當(dāng)用戶滾動的時候就重復(fù)變化這一小部分的DOM的渲染效果。這樣就能從原先幾千上萬個DOM變成現(xiàn)在的十個,減少了一個量級,減輕了渲染的壓力。而這一小部分顯示的區(qū)域暫稱之為視圖區(qū)域吧

審查元素,大致的效果如圖:

賊長的這部分是所有的數(shù)據(jù)的盒子所占的大小,但是每次只控制小部分?jǐn)?shù)據(jù)在上面的盒子進行顯示

虛擬列表的實現(xiàn)

怎么實現(xiàn)上面的效果?這里用到了固定定位和絕對定位

<script lang='ts' setup>
  type Item = {
    id: number
    name: string
  }
  const allListData = ref<Item[]>([])	// 存放十萬條數(shù)據(jù)
  const itemHeight = ref(40) // 每一條(項)的高度
  const count = ref(10) // 一屏展示幾條數(shù)據(jù)
  const startIndex = ref(0) // 開始位置的索引
  const endIndex = ref(10) // 結(jié)束位置的索引
  const topVal = ref(0) // 父元素滾動位置

  // 計算展示的列表
  const showListData = computed(() => allListData.value.slice(startIndex.value, endIndex.value))

  // 模擬十萬條數(shù)據(jù)
  const getData = async () => {
    for (let i = 0; i < 10000; i++) {
      allListData.value.push({ name: `第${i}條數(shù)據(jù)`, id: i })
    }
  }

  // 初始化加載
  onMounted(() => {
    getData()
  })

  // 虛擬列表視口區(qū)域的組件實例
  const viewport = ref<HTMLDivElement>()

    const handleScroll = () => {
      console.log('滾動了')
      // 非空判斷
      if (!viewport.value) return
      // 獲取滾動距離(這里通過組件實例獲取的,當(dāng)然也可以通過在該事件的事件參數(shù)中拿到)
      const scrollTop = viewport.value.scrollTop
      // 計算起始下標(biāo)和結(jié)束下標(biāo),用于 computed 計算
      startIndex.value = Math.floor(scrollTop / itemHeight.value)
      endIndex.value = startIndex.value + count.value
      // 動態(tài)更改定位的 top 值,動態(tài)展示相應(yīng)內(nèi)容
      topVal.value = viewport.value.scrollTop
    }
</script>

<template>
  <!-- 虛擬列表容器 -->
  <div
    class="viewport"
    ref="viewport"
    :style="{ height: 10條數(shù)據(jù)撐開的高度 }"
    >
    <!-- 占位元素,高度為所有的數(shù)據(jù)的總高度 -->
    <div
      class="placeholder"
      :style="{ height:itemHeight * count + 'px' }"
      ></div>
    <!-- 視圖區(qū),展示10條數(shù)據(jù),注意其定位的top值是變化的 -->
    <div class="list" :style="{ top: topVal + 'px' }">
      <!-- 每一條(項)數(shù)據(jù) -->
      <div
        v-for="item in showListData"
        :key="item.id"
        class="item"
        :style="{ height: itemHeight + 'px' }"
        >
        {{ item.name }}
      </div>
    </div>
  </div>
</template>

  <style scoped lang="scss">
  .viewport {
  box-sizing: border-box;
  width: 240px;
  border: solid 1px #000000;
  // 開啟滾動條
  overflow-y: auto;
  // 開啟相對定位
  position: relative;
  .list {
  width: 100%;
  height: auto;
  // 搭配使用絕對定位
  position: absolute;
  top: 0;
  left: 0;
  .item {
  box-sizing: border-box;
  width: 100%;
  height: 40px;
  line-height: 40px;
  text-align: center;
  // 隔行變色
  &:nth-child(even) {
  background: skyblue;
  }
  &:nth-child(odd) {
  background: #fff;
  }
  }
  }
  }
</style>

一開始視圖區(qū)域的top值為0,剛好在最頂端,監(jiān)聽滾動事件,當(dāng)滾動時實時改變top值以及該區(qū)域內(nèi)渲染的數(shù)據(jù),從而實現(xiàn)了虛擬列表

視圖區(qū)域的top值為什么要動態(tài)監(jiān)聽?試想一下,現(xiàn)在所有數(shù)據(jù)的總高度為1000px,視圖區(qū)域為100px,當(dāng)用戶滾動到500px時,如果視圖區(qū)域的top值不動態(tài)綁定,那么視圖區(qū)域還停留在top=0(也就是最頂端處),那肯定就看不到最新的視圖了

到此這篇關(guān)于詳解Vue如何手寫一個虛擬列表的文章就介紹到這了,更多相關(guān)Vue虛擬列表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解vuex commit保存數(shù)據(jù)技巧

    詳解vuex commit保存數(shù)據(jù)技巧

    這篇文章主要介紹了詳解vuex commit保存數(shù)據(jù)技巧,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • elementUI表格多選框this.$refs.xxx.toggleRowSelection無效問題

    elementUI表格多選框this.$refs.xxx.toggleRowSelection無效問題

    這篇文章主要介紹了elementUI表格多選框this.$refs.xxx.toggleRowSelection無效問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Vue v-text指令簡單使用方法示例

    Vue v-text指令簡單使用方法示例

    這篇文章主要介紹了Vue v-text指令簡單使用方法,結(jié)合實例形式分析了v-text指令文本輸出顯示簡單操作技巧,需要的朋友可以參考下
    2019-09-09
  • Vue中 v-if/v-show/插值表達式導(dǎo)致閃現(xiàn)的原因及解決辦法

    Vue中 v-if/v-show/插值表達式導(dǎo)致閃現(xiàn)的原因及解決辦法

    在開發(fā)過程中經(jīng)常會發(fā)現(xiàn)當(dāng)頁面明明不應(yīng)該出現(xiàn)的元素或內(nèi)容會閃現(xiàn)一下然后消失,這篇文章給大家分享Vue中 v-if/v-show/插值表達式導(dǎo)致閃現(xiàn)的原因及解決辦法,一起看看吧
    2018-10-10
  • vue的狀態(tài)管理模式vuex

    vue的狀態(tài)管理模式vuex

    本篇文章主要介紹了深入理解vue的狀態(tài)管理模式vuex,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • vue+koa2實現(xiàn)session、token登陸狀態(tài)驗證的示例

    vue+koa2實現(xiàn)session、token登陸狀態(tài)驗證的示例

    這篇文章主要介紹了vue+koa2實現(xiàn)session、token登陸狀態(tài)驗證的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 基于vue實現(xiàn)多引擎搜索及關(guān)鍵字提示

    基于vue實現(xiàn)多引擎搜索及關(guān)鍵字提示

    這篇文章主要為大家詳細(xì)介紹了基于vue實現(xiàn)多引擎搜索及關(guān)鍵字提示的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • vue實現(xiàn)購物車結(jié)算功能

    vue實現(xiàn)購物車結(jié)算功能

    這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)購物車結(jié)算功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • 前端框架之封裝Vue第三方組件三個技巧

    前端框架之封裝Vue第三方組件三個技巧

    這篇文章主要為大家介紹了前端框架封裝Vue第三方組件的三個技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • vue中@keyup.enter失效問題及解決

    vue中@keyup.enter失效問題及解決

    這篇文章主要介紹了vue中@keyup.enter失效問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10

最新評論