Vue實(shí)現(xiàn)滾動加載更多效果的示例代碼
引言
在現(xiàn)代Web應(yīng)用中,處理大量數(shù)據(jù)的展示是一個(gè)常見的挑戰(zhàn)。無論是社交媒體的時(shí)間線、電商平臺的商品列表,還是新聞網(wǎng)站的文章流,如何高效地加載和渲染大量內(nèi)容,同時(shí)保持良好的用戶體驗(yàn),是開發(fā)者需要解決的關(guān)鍵問題。傳統(tǒng)的做法是將所有數(shù)據(jù)一次性加載到頁面上,但這會導(dǎo)致頁面加載緩慢、內(nèi)存占用過高,甚至影響瀏覽器的響應(yīng)速度。為了解決這些問題,滾動加載更多(Infinite Scroll) 和 虛擬列表(Virtual List) 成為了流行的解決方案。
兩種方案的介紹以及區(qū)別
滾動加載更多(Infinite Scroll) :
- 工作原理:滾動加載更多通過分頁的方式工作。當(dāng)用戶滾動到頁面底部或接近底部時(shí),系統(tǒng)會觸發(fā)一個(gè)新的請求,獲取下一頁的數(shù)據(jù),并將其動態(tài)添加到現(xiàn)有內(nèi)容的末尾。這種方式允許用戶在不中斷瀏覽的情況下,無縫加載更多內(nèi)容。
- 優(yōu)點(diǎn):實(shí)現(xiàn)簡單,用戶體驗(yàn)流暢,減少了初始加載時(shí)間。
- 缺點(diǎn):隨著用戶不斷滾動,頁面上的DOM元素會逐漸增加,可能導(dǎo)致內(nèi)存占用過高,影響性能。對于非常大的數(shù)據(jù)集,滾動加載更多可能會導(dǎo)致頁面變得非常沉重,影響用戶體驗(yàn)。
虛擬列表(Virtual List) :
- 工作原理:虛擬列表的核心思想是只渲染當(dāng)前視口(即用戶可以看到的部分)中的內(nèi)容,而不是一次性將所有數(shù)據(jù)加載到DOM中。當(dāng)用戶滾動時(shí),虛擬列表會動態(tài)地更新DOM,確保只有可見區(qū)域的內(nèi)容被渲染。此外,虛擬列表通常會復(fù)用DOM節(jié)點(diǎn),進(jìn)一步減少DOM操作的開銷。
- 優(yōu)點(diǎn):即使數(shù)據(jù)量非常大,虛擬列表也能保持良好的性能,因?yàn)樗讳秩究梢妳^(qū)域的內(nèi)容。它還非常適合處理海量數(shù)據(jù),避免了內(nèi)存占用過高的問題。
- 缺點(diǎn):實(shí)現(xiàn)相對復(fù)雜,尤其是需要處理滾動事件、DOM復(fù)用、邊界條件等。通常建議使用現(xiàn)成的庫(如
vue-virtual-scroller
、react-window
等)來簡化開發(fā)過程。
滾動加載更多的實(shí)現(xiàn)
使用@scroll
1. 實(shí)現(xiàn)
通過監(jiān)聽滾動條的變化來更新頁碼,實(shí)現(xiàn)加載更多效果;代碼里面有注釋,我就不多說啦。需要注意的是父盒子的高度很重要。
以下是代碼(但是先別拿去用,因?yàn)檫€有重要的優(yōu)化)
<template> <div class="color-squares" @scroll="handleScroll"> <!-- 這里我使用的是一個(gè)數(shù)字并非是一個(gè)數(shù)組,如果使用的是數(shù)組的話可將size換成arr.slice(0,size)(arr是你的數(shù)組); --> <div v-for="(item, index) in size" :key="index" class="square"> {{ item }} </div> <!-- 末尾方式加載狀態(tài),這里我使用的時(shí)t-design(騰訊組件庫) --> <t-loading :loading="loading" text="正在加載更多..." /> </div> </template>
<script setup> import { ref, onMounted, computed } from "vue"; //總數(shù)據(jù)量 const total = ref(15); //我們手動模擬分頁效果, const pageSize = ref(5); const pageNum = ref(1); const loading = ref(false); //使用計(jì)算屬性來更改size的值。通過滾動來更改pageNum(頁碼)。 const size = computed(() => { return pageNum.value * pageSize.value > total ? total : pageNum.value * pageSize.value; }); //加載更多函數(shù),注意里面的打印信息。 const loadMore = () => { if (pageNum.value * pageSize.value >= total.value) { loading.value = false; return; } loading.value = true; //請注意我 console.log(1); // 模擬異步請求 setTimeout(() => { pageNum.value++; loading.value = false; }, 1000); // 模擬網(wǎng)絡(luò)延遲 }; const handleScroll = (event) => { const container = event.target; if ( container.scrollTop + container.clientHeight >= container.scrollHeight - 5 ) { loadMore(); } }; // 生命周期鉤子 onMounted(() => {}); </script>
<style scoped> .color-squares { height: 100vh; overflow-y: scroll; display: flex; flex-direction: column; align-items: center; text-align: center; line-height: 100px; width: 100%; gap: 10px; border: 1px solid #ccc; } .square { width: 200px; height: 200px; background-color: #ececec; text-align: center; line-height: 200px; border-radius: 8px; font-size: 24px; font-weight: bolder; } </style>
2. 上述的缺陷以及優(yōu)化
直接看效果圖,我們可以看到我們輕輕滾動一下,loadMore就觸發(fā)了多次。注意控制臺打印信息打印的13個(gè)1,意味著一次滾動觸發(fā)了loadMore 13次
所以我們理所當(dāng)然需要給他加上防抖
<script setup> import { ref, onMounted, computed } from "vue"; //總數(shù)據(jù)量 const total = ref(15); //我們手動模擬分頁效果, const pageSize = ref(5); const pageNum = ref(1); const loading = ref(false); //使用計(jì)算屬性來更改size的值。通過滾動來更改pageNum(頁碼)。 const size = computed(() => { return pageNum.value * pageSize.value > total ? total : pageNum.value * pageSize.value; }); //加載更多函數(shù),注意里面的打印信息。 const loadMore = () => { if (pageNum.value * pageSize.value >= total.value) { loading.value = false; return; } loading.value = true; //請注意我 console.log(1); // 模擬異步請求 setTimeout(() => { pageNum.value++; loading.value = false; }, 1000); // 模擬網(wǎng)絡(luò)延遲 }; function debounce(fn, delay, immediate = false) { let timer; return function (...args) { const context = this; // 如果設(shè)置了 immediate,并且這是第一次觸發(fā),則立即執(zhí)行目標(biāo)函數(shù) if (immediate && !timer) { fn.apply(context, args); } // 清除之前的定時(shí)器 if (timer) clearTimeout(timer); // 設(shè)置新的定時(shí)器 timer = setTimeout(() => { if (!immediate) { fn.apply(context, args); // 如果沒有立即執(zhí)行,則在延遲后執(zhí)行 } timer = null; // 清空定時(shí)器標(biāo)識符 }, delay); }; } const handleScroll = debounce((event) => { const container = event.target; if ( container.scrollTop + container.clientHeight >= container.scrollHeight - 5 ) { loadMore(); } }, 300); // 生命周期鉤子 onMounted(() => {}); </script>
加了防抖的效果
使用 Element Plus 的無限滾動指令 (v-infinite-scroll)(最快)
在需要添加無限滾動的盒子中加上 v-infinite-scroll指令該指令需要綁定一個(gè)函數(shù)。無需設(shè)置防抖,無需監(jiān)聽滾動,拿來即用。
具體代碼如下:
<template> <div class="color-squares" max-height="500px" v-infinite-scroll="loadMore"> <!-- 如果使用的是數(shù)組,可以將 size 換成 arr.slice(0, size) --> <div v-for="(item, index) in size" :key="index" class="square"> {{ item }} </div> <!-- 末尾方式加載狀態(tài),這里我使用的時(shí) t-design(騰訊組件庫) --> <t-loading :loading="loading" text="正在加載更多..." /> </div> </template>
<script setup> import { ref, onMounted, computed } from "vue"; //總數(shù)據(jù)量 const total = ref(15); //我們手動模擬分頁效果, const pageSize = ref(5); const pageNum = ref(1); const loading = ref(false); //使用計(jì)算屬性來更改size的值。通過滾動來更改pageNum(頁碼)。 const size = computed(() => { return pageNum.value * pageSize.value > total ? total : pageNum.value * pageSize.value; }); //加載更多函數(shù),注意里面的打印信息。 const loadMore = () => { if (pageNum.value * pageSize.value >= total.value) { loading.value = false; return; } loading.value = true; //請注意我 console.log(1); // 模擬異步請求 setTimeout(() => { pageNum.value++; loading.value = false; }, 1000); // 模擬網(wǎng)絡(luò)延遲 }; </script>
<style scoped> .color-squares { display: flex; flex-direction: column; align-items: center; text-align: center; line-height: 100px; width: 100%; gap: 10px; border: 1px solid #ccc; /* 可選:添加邊框以便更清晰地看到滾動容器 */ } .square { width: 200px; height: 200px; background-color: #ececec; text-align: center; line-height: 200px; border-radius: 8px; font-size: 24px; font-weight: bolder; } </style>
看看效果圖:
結(jié)語
通過本期文章,我們掌握了兩種常見的滾動加載更多實(shí)現(xiàn)方式:手動處理滾動事件 和 使用 Element Plus 的無限滾動指令。這兩種方法各有優(yōu)劣,適用于不同的場景。在下一期文章中,我們將進(jìn)一步探討如何使用 Intersection Observer API 來檢測元素的重疊度,從而實(shí)現(xiàn)更加靈活和高效的滾動加載更多功能。
以上就是Vue實(shí)現(xiàn)滾動加載更多效果的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Vue滾動加載更多效果的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue使用高德地圖搭建實(shí)時(shí)公交應(yīng)用功能(地圖 + 附近站點(diǎn)+線路詳情 + 輸入提示+換乘詳情)
這篇文章主要介紹了vue中使用高德地圖搭建實(shí)時(shí)公交應(yīng)用(地圖 + 附近站點(diǎn)+線路詳情 + 輸入提示+換乘詳情),主要是讓大家熟悉下高德地圖在vue中的使用及vue的常用指令,需要的朋友可以參考下2018-05-05vue ssr+koa2構(gòu)建服務(wù)端渲染的示例代碼
這篇文章主要介紹了vue ssr+koa2構(gòu)建服務(wù)端渲染的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03使用Vue-scroller頁面input框不能觸發(fā)滑動的問題及解決方法
這篇文章主要介紹了使用Vue-scroller頁面input框不能觸發(fā)滑動的問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08