淘寶上有做網(wǎng)站的嗎某個網(wǎng)站seo分析實(shí)例
文章目錄
- 安裝 vue-virtual-scroller
- 引入
- 📢注意事項
- 使用
- 基礎(chǔ)使用
- 上拉加載
- 下拉刷新
移動端在渲染長列表時 大量dom節(jié)點(diǎn)的渲染和重繪重排會導(dǎo)致頁面卡頓、滾動不流暢、設(shè)備耗電加快、影響移動設(shè)備電池壽命等性能問題
這里分享使用【虛擬滾動】方案進(jìn)行長列表優(yōu)化,以Vue3為例,推薦使用 vue-virtual-scroller
先列舉 vue-virtual-scroller
相關(guān)官方文檔幫助學(xué)習(xí)
- 官方文檔
- Live demo
- Live demo 源碼
- Video demo
安裝 vue-virtual-scroller
npm install --save vue-virtual-scroller@next
yarn add vue-virtual-scroller@next
引入
安裝所有組件:
import VueVirtualScroller from 'vue-virtual-scroller'app.use(VueVirtualScroller)
按需引入組件:
import { RecycleScroller } from 'vue-virtual-scroller'app.component('RecycleScroller', RecycleScroller)
引入樣式文件
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
📢注意事項
- 整個列表的高度要寫死,不然會將整改列表作為可視區(qū)域,會出現(xiàn)渲染全部數(shù)據(jù)而不是只渲染可視區(qū)域的問題;
這里推薦使用flex: 1;
實(shí)現(xiàn),比height: calc(100vh - 30vw);
更優(yōu)雅、更易維護(hù) - 使用
-webkit-overflow-scrolling: touch;
開啟硬件加速,ios高版本自帶 - 使用
overscroll-behavior: none;
禁用iOS回彈效果
使用
使用 DynamicScroller
組件渲染不確定高度的組件
基礎(chǔ)使用
<div class="content-wrap"><DynamicScroller:items="dataList":min-item-size="160"key-field="id"class="virtual-scroller"><template #default="{ item, index, active }"><DynamicScrollerItem:item="item":active="active":size-dependencies="[item.status, item.type]":data-index="index"class="virtual-scroller-item"><!-- 渲染組件 --><TaskItem :data="item" /></DynamicScrollerItem></template></DynamicScroller>
</div>
.icc__container {height: 100vh;display: flex;flex-direction: column;box-sizing: border-box;.icc__content-wrap {flex: 1;.virtual-scroller {/* 開啟硬件加速 -webkit-overflow-scrolling: touch; ios高版本自帶 */-webkit-overflow-scrolling: touch;/* 禁用回彈效果 */overscroll-behavior: none;height: 100%;}}
}
上拉加載
vant List
+ DynamicScroller
會導(dǎo)致連續(xù)觸發(fā) vant List
load 事件,所以只能手寫上拉加載
- 監(jiān)聽
DynamicScroller
滾動事件,如果當(dāng)前距離頂部的值加上可視區(qū)域的值大于等于總高度,則滾動條觸底,加載更多 - 使用
DynamicScroller
after
插槽,定義加載中、加載完成、加載失敗等狀態(tài)
<div class="content-wrap"><DynamicScroller:items="dataList":min-item-size="160"key-field="id"class="virtual-scroller"@scroll="handleDynamicScrollerScroll"><template #default="{ item, index, active }"><DynamicScrollerItem:item="item":active="active":size-dependencies="[item.status, item.type]":data-index="index"class="virtual-scroller-item"><!-- 渲染組件 --><TaskItem :data="item" /></DynamicScrollerItem></template><template #after><div class="after"><van-loading v-show="loadMoreLoading">加載中...</van-loading><span v-show="finished">沒有更多了</span><span v-show="loadError" @click="handleLoadMore">請求失敗,點(diǎn)擊重新加載</span></div></template></DynamicScroller>
</div>
// 上拉loading
const loadMoreLoading = ref<boolean>(false)
// 沒有更多數(shù)據(jù)了
const finished = ref<boolean>(false)
// 加載失敗
const loadError = ref<boolean>(false)// 實(shí)現(xiàn)上拉加載
const handleDynamicScrollerScroll = (e: Event) => {// 距頂部const scrollTop = (e.target as HTMLDivElement)?.scrollTop || 0// 可視區(qū)高度const clientHeight = (e.target as HTMLDivElement).clientHeight || 0// 滾動條總高度const scrollHeight = (e.target as HTMLDivElement)?.scrollHeight || 0// 觸底距離const offset = 300// 如果當(dāng)前距離頂部的值加上可視區(qū)域的值大于等于總高度,則滾動條觸底if (scrollTop + clientHeight >= scrollHeight - offset) {if (!loadMoreLoading.value && !finished.value && !loadError.value) {console.log('滾動到底部了')loadMoreLoading.value = truehandleLoadMore()}}
}
下拉刷新
使用 vant PullRefresh
實(shí)現(xiàn)下拉刷新
如果直接用 vant PullRefresh
包裹虛擬滾動,會導(dǎo)致無法向下滑動,任何位置下拉都會觸發(fā)下拉刷新。
解決方案:
1. `vant PullRefresh` 中有 `disabled` 選項,可以禁用下拉刷新,默認(rèn)設(shè)置為 `false`
2. 監(jiān)聽滾動條滾動事件中的 `scrollTop`,
3. 如果 `scrollTop` 小于4,則將 `disabled` 變?yōu)?`false`
4. 否則將 `disabled` 變?yōu)?`true`
<template><div class="container"><van-pull-refreshv-model="refreshLoading"@refresh="handlerefresh":disabled="disabledPullRefresh"class="content-wrap"><template v-if="dataList.length > 0"><DynamicScroller:items="dataList":min-item-size="160"key-field="id"class="virtual-scroller"id="virtual-scroller"@scroll="handleDynamicScrollerScroll"><template #default="{ item, index, active }"><DynamicScrollerItem:item="item":active="active":size-dependencies="[item.status, item.type]":data-index="index"class="virtual-scroller-item"><!-- 渲染組件 --><TaskItem :data="item" /></DynamicScrollerItem></template><template #after><div class="after"><van-loading v-show="loadMoreLoading">加載中...</van-loading><span v-show="finished">沒有更多了</span><span v-show="loadError" @click="handleLoadMore">請求失敗,點(diǎn)擊重新加載</span></div></template></DynamicScroller></template><van-emptyv-elseimage="./no_data.png"description="暫無匹配數(shù)據(jù)":image-size="['60vw', 'auto']"class="h-80vh"/></van-pull-refresh></div><van-back-top target="#virtual-scroller" />
</template>
// 下拉loading
const refreshLoading = ref<boolean>(false)
// 禁用下拉刷新
const disabledPullRefresh = ref(false)
// 上拉loading
const loadMoreLoading = ref<boolean>(false)
// 沒有更多數(shù)據(jù)了
const finished = ref<boolean>(false)
// 加載失敗
const loadError = ref<boolean>(false)
// 實(shí)現(xiàn)上拉加載
const handleDynamicScrollerScroll = (e: Event) => {// 距頂部const scrollTop = (e.target as HTMLDivElement)?.scrollTop || 0// 可視區(qū)高度const clientHeight = (e.target as HTMLDivElement).clientHeight// 滾動條總高度const scrollHeight = (e.target as HTMLDivElement)?.scrollHeightconst offset = 300// 如果直接用 `vant PullRefresh` 包裹虛擬滾動,會導(dǎo)致無法向下滑動,任何位置下拉都會觸發(fā)下拉刷新。// 控制是否開啟下拉刷新if (scrollTop <= 4) {disabledPullRefresh.value = false} else {disabledPullRefresh.value = true}// 如果當(dāng)前距離頂部的值加上可視區(qū)域的值大于等于總高度,則滾動條觸底if (scrollTop + clientHeight >= scrollHeight - offset) {if (!loadMoreLoading.value && !finished.value && !loadError.value) {console.log('滾動到底部了')loadMoreLoading.value = truehandleLoadMore()}}
}
兄弟們,上面的代碼在項目中踩坑實(shí)測過了!!
源碼就不貼了😄