切換語言為:簡體
虛擬列表技術透過只渲染當前可視區域的資料項,可極大地提高了列表的渲染效能!

虛擬列表技術透過只渲染當前可視區域的資料項,可極大地提高了列表的渲染效能!

  • 爱糖宝
  • 2024-09-26
  • 2049
  • 0
  • 0

引言

隨著Web應用程式的發展,使用者對資料展示的需求日益增加。在一些場景下,我們需要在一個頁面中展示成千上萬條資料記錄,如訊息列表、商品列表等。傳統的做法是將所有資料一次性載入到頁面中,但這會導致頁面載入速度緩慢,使用者體驗不佳。爲了解決這個問題,虛擬列表(Virtual Scrolling)技術應運而生。本文將詳細介紹虛擬列表的概念、實現原理及其在Vue.js中的具體實現。

什麼是虛擬列表?

虛擬列表是一種最佳化技術,用於在Web應用中高效地渲染大量資料。它的核心思想是隻渲染當前可視區域的資料項,而不是一次性渲染整個資料集。這樣可以顯著減少記憶體消耗和提高頁面效能。

虛擬列表的工作原理

虛擬列表透過以下幾個步驟來提高列表的渲染效率:

  1. 計算可視區域:確定當前滾動到的位置以及可視區域的高度。

  2. 確定需要渲染的資料範圍:基於可視區域的高度和每項資料的高度,計算出需要顯示的資料項範圍。

  3. 動態調整渲染範圍:隨著使用者的滾動操作,動態更新需要渲染的資料項範圍。

  4. 重用元素:如果可能的話,重用已經建立的DOM節點,而不是每次都建立新的節點。

虛擬列表技術透過只渲染當前可視區域的資料項,可極大地提高了列表的渲染效能!

Vue.js 中的虛擬列表實現

下面我們將詳細介紹上述程式碼是如何實現虛擬列表功能的:

HTML 結構
<template>
    <div ref="listRef" class="infinte-list-container" @scroll="scrollHandle">
      <div class="empty" :style="{height: itemSize * listData.length + 'px'}"></div>
      <div class="infinte-list" :style="{transform: getTransform}">
        <div 
          class="infinte-list-item"
          v-for="item in visibleData"
          :key="item.id"
          :style="{height: itemSize + 'px', lineHeight: itemSize + 'px'}"
        >
          {{item.value}}
        </div>
      </div>
    </div>
</template>

  • listRef 是對包含列表的div元素的引用,透過它可以獲取到滾動事件。

  • class="infinte-list-container" 是包含列表的容器,它具有捲軸。

  • class="empty" 是一個佔位符,它的高度等於所有資料項的高度總和,確保列表的總高度正確。

  • class="infinte-list" 包含實際要顯示的資料項,使用transform來模擬滾動效果。

  • v-for 指令用於遍歷visibleData陣列,動態渲染資料項。

JavaScript 邏輯
<script setup>
import { ref } from 'vue';
import { computed } from 'vue';
import { reactive, onMounted } from 'vue';

const props = defineProps({
listData: {
  type: Array,
  default: () => []
},
itemSize: {
  type: Number,
  default: 50
}
})

const state = reactive({
scrollHeight: 0,
start: 0,
end: 0,
listOffset: 0
})

// 可視區域能展示幾條
const visibleCount = computed(() => {
return Math.ceil(state.scrollHeight / props.itemSize)
})

// 可視區域要展示的資料
const visibleData = computed(() => {
return props.listData.slice(state.start, Math.min(state.end, props.listData.length))
})

// 列表被帶出去後移回
const getTransform = computed(() => {
return `translateY(${state.listOffset}px)`
})

const listRef = ref(null)
onMounted(() => {
state.scrollHeight = listRef.value.clientHeight
state.end = state.start + visibleCount.value
})

const scrollHandle = () => {
let scrollTop = listRef.value.scrollTop
state.start = Math.floor(scrollTop / props.itemSize)
state.end = state.start + visibleCount.value
state.listOffset = scrollTop - (scrollTop % props.itemSize)
// console.log(scrollTop);
// 實時計算 start 和 end
}
</script>

  • listData 是傳入元件的資料陣列。

  • itemSize 是每個資料項的高度。

  • state 儲存元件的狀態,如可視區域的高度、開始和結束索引等。

  • visibleCount 計算可視區域內可以展示的資料項的數量。

  • visibleData 根據可視區域的起始和結束索引,擷取需要顯示的資料項。

  • getTransform 計算列表的translateY值,用於模擬滾動效果。

  • listRef 用於引用 DOM 元素。在元件掛載完成後,確保元件正確初始化。

  • scrollHandle 監聽滾動事件,更新狀態。

CSS 樣式
<style scoped>
.infinte-list-container{
height: 100%;
overflow: auto;
position: relative;
}
.infinte-list{
position: absolute;
left: 0;
right: 0;
top: 0;
}
.infinte-list-item{
text-align: center;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
</style>

  • .infinte-list-container 定義了包含列表的容器樣式,包括高度、捲軸和相對定位。

  • .infinte-list 定義了列表本身的位置樣式,絕對定位以便使用transform

  • .infinte-list-item 定義了每個列表項的樣式,包括居中文字、底部邊框等。

下面請看例項演示(最終就是如圖效果):

虛擬列表技術透過只渲染當前可視區域的資料項,可極大地提高了列表的渲染效能!

總結

透過以上介紹,我們可以看到虛擬列表技術透過只渲染當前可視區域的資料項,極大地提高了列表的渲染效能。Vue.js 提供了強大的響應式系統和生命週期鉤子,使得實現虛擬列表變得更加簡單和直觀。虛擬列表不僅適用於列表,還可以應用於表格、卡片等多種UI元件中,是一個值得掌握的技術。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.