最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3虛擬列表的實現原理與實戰(zhàn)指南

 更新時間:2026年03月20日 10:05:41   作者:寧雨橋  
在日常開發(fā)中,我們經常會遇到需要展示大量數據的場景,比如展示幾千條甚至上萬條數據列表,如果直接將所有數據渲染到頁面中,會導致嚴重的性能問題,虛擬列表正是為了解決這一問題而誕生的技術,本文將介紹虛擬列表的核心原理,并基于 Vue3 手寫一個完整的虛擬列表組件

前言

在日常開發(fā)中,我們經常會遇到需要展示大量數據的場景,比如展示幾千條甚至上萬條數據列表。如果直接將所有數據渲染到頁面中,會導致嚴重的性能問題,頁面會變得卡頓甚至崩潰。虛擬列表(Virtual List)正是為了解決這一問題而誕生的技術。

本文將介紹虛擬列表的核心原理,并基于 Vue3 手寫一個完整的虛擬列表組件。

一、什么是虛擬列表

虛擬列表是一種按需渲染的技術,它只渲染當前可視區(qū)域內的列表項,而不是一次性渲染所有數據。想象一下,你有一本1000頁的書,但你在任何時候只能看到其中的一頁。虛擬列表的工作方式就和翻書一樣——只展示當前"看得到"的內容。

虛擬列表的核心優(yōu)勢

優(yōu)勢說明
性能提升只渲染可見區(qū)域的數據,DOM 節(jié)點數量大幅減少
內存優(yōu)化避免創(chuàng)建大量 DOM 節(jié)點,降低內存占用
流暢體驗滾動更加流暢,不會因為數據量大而卡頓
快速首屏首屏渲染時間大大縮短

二、虛擬列表的實現原理

虛擬列表的核心思想其實很簡單,可以用以下幾個步驟來概括:

  1. 計算可視區(qū)域:根據滾動位置和容器高度,計算出當前可見的數據范圍
  2. 按需渲染:只渲染計算出的可見數據,而不是全部數據
  3. 占位模擬:通過 padding 或 transform 模擬完整的滾動高度,讓滾動條看起來正常

下面這張圖清晰地展示了虛擬列表的工作原理:

┌─────────────────────────────┐
│  已渲染區(qū)域(可見)           │
│  ┌─────────────────────┐     │
│  │ Item 3              │     │
│  │ Item 4              │     │
│  │ Item 5              │     │ ← 當前可見區(qū)域
│  │ Item 6              │     │
│  │ Item 7              │     │
│  └─────────────────────┘     │
├─────────────────────────────┤
│  未渲染區(qū)域(不可見)         │
│  ... Item 8-100              │
└─────────────────────────────┘

三、代碼實現

子組件:MyList.vue

<template>
    <div style="overflow-y:auto ;border:3px solid blue;position: relative;" :style="{ height:props.size * 10 + 'px'}" @scroll="handSrool">
        <ul :style="{ height:(props.size+1) * props.testData.length + 'px', transform: `translateY(${offsetY}px)` }" >
            <li v-for="(item, index) in list" class="list-item" :style="{ height:props.size + 'px', position: 'absolute', top: (index * props.size) + 'px', width: '100%' }">
                {{ item }}
            </li>
        </ul>
    </div>
</template>
<script setup>
import { onMounted, ref, computed } from 'vue';
// 接受父節(jié)點參數
const props = defineProps({
    testData: Array,
    size: {
        type: Number,
        default: '6'
    }
})
const startIndex = ref(0)
const endIndex = computed(() => startIndex.value + 10)
// 計算偏移量,讓列表項跟隨滾動
const offsetY = computed(() => startIndex.value * props.size)
const list = computed(() => props.testData.slice(startIndex.value, endIndex.value))
// 監(jiān)聽滾動
const handSrool = (e) => {
    // 獲取滾動距離
    const scrollTop = e.target.scrollTop
    // 根據滾動距離計算起始索引
    startIndex.value = Math.floor(scrollTop / props.size)
}
onMounted(() => {
    console.log(props.size)
    console.log(endIndex.value)
})
</script>
<style>
.list-item {
    font-size: 16px;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid rgb(146, 144, 144);
}
</style>

父組件:使用示例

<script setup>
import MyList from './components/MyList.vue';
const data = []
// 模擬數據
for (let i = 0; i < 100; i++) {
  data.push({
    id: i,
    name: `name${i}`,
    age: i,
    sex: i % 2 === 0 ? '男' : '女',
    address: `address${i}`,
    date: new Date(),
  })
}
</script>
<template>
  <div class="table_continue">
     <MyList :testData="data" :size="60"/>
  </div>
</template>
<style scoped>
.table_continue {
  padding: 20px;
}
</style>

四、核心實現解析

1. 計算可見區(qū)域的起始索引

const handSrool = (e) => {
    const scrollTop = e.target.scrollTop
    startIndex.value = Math.floor(scrollTop / props.size)
}

這是虛擬列表最核心的邏輯。當用戶滾動時,我們通過 scrollTop 獲取滾動距離,然后除以單個列表項的高度,就能計算出當前應該從第幾條數據開始渲染。

為什么要這樣做?

假設每個列表項高度是 60px,滾動位置是 300px,那么 300 / 60 = 5,說明用戶已經滾過了5個列表項,所以我們應該從第5條數據開始渲染。

2. 計算可見數據

const list = computed(() => props.testData.slice(startIndex.value, endIndex.value))

使用 slice 方法截取數組中的一部分,只渲染從 startIndex 開始的 10 條數據。這樣無論原數組有多大,DOM 中最多只有 10 個列表項元素。

3. 使用 transform 模擬滾動

const offsetY = computed(() => startIndex.value * props.size)

這是實現無縫滾動的關鍵。雖然我們只渲染了 10 條數據,但通過 transform: translateY() 將整個列表向下偏移,偏移量等于被"跳過"的數據的總高度。這樣用戶看起來就像在滾動整個列表一樣。

4. 占位容器的高度

:style="{ height:(props.size+1) * props.testData.length + 'px' }"

外層容器的高度等于單個列表項高度乘以總數據條數,這就是讓滾動條看起來正常的"秘密"。瀏覽器會根據這個高度生成相應長度的滾動條,用戶拖動滾動條時就會觸發(fā) scroll 事件。

五、性能優(yōu)化建議

雖然上面的實現已經能夠正常工作,但在生產環(huán)境中,你可能還需要考慮以下優(yōu)化點:

1. 預渲染更多數據

可以在可見區(qū)域的前后各多渲染幾條數據,避免快速滾動時出現空白:

const BUFFER = 3
const endIndex = computed(() => startIndex.value + 10 + BUFFER)
const list = computed(() => {
    const start = Math.max(0, startIndex.value - BUFFER)
    return props.testData.slice(start, endIndex.value)
})

2. 使用防抖處理滾動事件

如果數據量非常大,可以使用防抖來減少計算頻率:

import { debounce } from 'lodash-es'

const handSrool = debounce((e) => {
    const scrollTop = e.target.scrollTop
    startIndex.value = Math.floor(scrollTop / props.size)
}, 16)

3. 處理列表項高度不一致的情況

在實際應用中,列表項的高度可能是動態(tài)的。這時可以使用測量行高的方案,或者將所有列表項設為固定高度。

4. 使用 CSS will-change 優(yōu)化動畫

.list-item {
    will-change: transform;
}

這告訴瀏覽器該元素會發(fā)生變化,可以提前進行優(yōu)化。

六、原理圖解

讓我們通過一張圖來理解整個虛擬列表的工作流程:

用戶滾動 → 獲取 scrollTop → 計算 startIndex → slice 取數據 → translateY 偏移
     │                                              │
     ↓                                              ↓
┌─────────┐    ┌─────────────┐    ┌──────────┐    ┌────────────┐
│ 滾動事件 │ →  │ scrollTop   │ →  │ 300/60=5  │ →  │ 取第5-15條  │
│ 觸發(fā)    │    │ = 300px     │    │ start=5   │    │ translateY │
└─────────┘    └─────────────┘    └──────────┘    │ = 300px    │
                                                   └────────────┘

七、總結

虛擬列表是前端性能優(yōu)化中非常重要的技術之一。它的核心思想可以用一句話概括:只渲染可見的內容,用占位符模擬完整的滾動高度。

通過本文的實現,我們可以看到一個基礎的虛擬列表組件并不復雜,主要涉及到以下幾個關鍵點:

  1. 監(jiān)聽滾動事件:獲取用戶的滾動位置
  2. 計算可見索引:根據滾動位置計算應該顯示的數據范圍
  3. 按需渲染:只渲染計算范圍內的數據
  4. 模擬滾動:通過 transform 或 padding 模擬完整的滾動高度

掌握了這些核心原理后,你就可以在此基礎上進行各種定制化開發(fā),比如支持動態(tài)高度的列表項、添加加載更多功能、實現分組虛擬列表等。

以上就是Vue3虛擬列表的實現原理與實戰(zhàn)指南的詳細內容,更多關于Vue3虛擬列表實現的資料請關注腳本之家其它相關文章!

相關文章

  • 基于vue2實現上拉加載功能

    基于vue2實現上拉加載功能

    這篇文章主要為大家詳細介紹了基于vue2實現上拉加載功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • vue router返回到指定的路由的場景分析

    vue router返回到指定的路由的場景分析

    這篇文章主要介紹了vue router返回到指定的路由的場景分析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • vue中的mixins混入使用方法

    vue中的mixins混入使用方法

    這篇文章主要介紹了vue中的mixins混入使用方法,混入又分全局混入混入局部混入,下文對兩者都有相關介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04
  • Vue中Vue-Baidu-Map基本使用方法實例

    Vue中Vue-Baidu-Map基本使用方法實例

    最近有一個項目需要用到地圖來展示位置并進行數據交互,用vue-baidu-map實現出來,下面這篇文章主要給大家介紹了關于Vue中Vue-Baidu-Map基本使用的相關資料,需要的朋友可以參考下
    2023-03-03
  • vue3中如何使用mqtt數據傳輸

    vue3中如何使用mqtt數據傳輸

    這篇文章主要為大家詳細介紹了vue3中如何使用mqtt數據傳輸,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-11-11
  • vue 實現錨點功能操作

    vue 實現錨點功能操作

    這篇文章主要介紹了vue 實現錨點功能操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • 在Vue3和TypeScript中大文件分片上傳的實現與優(yōu)化

    在Vue3和TypeScript中大文件分片上傳的實現與優(yōu)化

    本文介紹在 Vue 3 和 TypeScript 環(huán)境下大文件分片上傳的實現與優(yōu)化,包括項目前后端技術棧,前端的文件切片、并發(fā)上傳、計算 Hash、斷點續(xù)傳和用戶體驗優(yōu)化,后端的文件接收存儲、切片合并、異常處理與日志記錄,還提及遇到的問題及解決方案,總結了此方式的優(yōu)勢和重要性
    2025-01-01
  • vue中computed和watch的使用實例代碼解析

    vue中computed和watch的使用實例代碼解析

    這篇文章主要介紹了vue中computed和watch的綜合運用實例,主要需求是點擊按鈕實現天氣的切換效果結合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • vue如何處理base64格式文件pdf及圖片預覽功能

    vue如何處理base64格式文件pdf及圖片預覽功能

    這篇文章主要給大家介紹了關于vue如何處理base64格式文件pdf及圖片預覽功能的相關資料,圖片的base64編碼就是可以將一副圖片數據編碼成一串字符串,使用該字符串代替圖像地址,需要的朋友可以參考下
    2024-05-05
  • vue改變對象或數組時的刷新機制的方法總結

    vue改變對象或數組時的刷新機制的方法總結

    這篇文章主要介紹了vue改變對象或數組時的刷新機制的方法總結,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04

最新評論

治县。| 巩义市| 星座| 崇仁县| 达日县| 高邮市| 筠连县| 博客| 平泉县| 宜兴市| 邹城市| 长顺县| 丁青县| 双柏县| 罗甸县| 贵州省| 隆安县| 南宁市| 弋阳县| 额尔古纳市| 城市| 霸州市| 沁源县| 额敏县| 贡山| 二手房| 泾川县| 石嘴山市| 皮山县| 揭东县| 安远县| 望谟县| 永春县| 和龙市| 师宗县| 茶陵县| 红桥区| 龙门县| 繁峙县| 南岸区| 双江|