上拉加載

上拉加載 下拉更新 原本是 APP 很常見的功能
現在 Web 也很常見 因為越來越多的 Web 得做得和 APP 越來越像 …

今天這篇先講上拉加載的部分:

  • scrollHeight + clientHeight + scrollTop

scrollHeight + clientHeight + scrollTop

實現加載的關鍵就在滾動事件

當長清單列表的元素滾動到底部時
得觸發一個 Callback function 來獲取新的資料
並將此資料加入原清單列表的陣列當中

這邊先看一下偵測滾動到底部的代碼:

1
2
3
4
5
6
7
8
const detectScrollToBottom = () => {
const { clientHeight, scrollHeight, ScrollTop } = document.querySelector('#el');
if(clientHeight + ScrollTop >= scrollHeight) {
console.log('已滑動至底部')
}
}

document.querySelector('#el').addEventListener('scroll', () => detectScrollToBottom());

首先解釋一下元素解構出來的這幾個屬性意思

scrollHeightclientHeightscrollTop
元素可視與不可視區的高度元素可視區的高度元素可視區頂部到元素不可視區頂部的距離

基本上 scrollHeight 與 clientHeight 都是固定的高度
只有 scrollTop 會隨著滾動而改變數值
當 clientHeight + ScrollTop 的數值 大於等於 scrollHeight 就表示到了底部

但實際上

這樣寫會有問題
因為scrollTop 在滾動時會有浮點數(0.5)
而浮點數可能會造成計算的不精準
像是明明已經滑動到底部了
但是因為差0.5而沒有偵測到底部去觸發回函

所以這邊可以加上 1 來作為緩衝

1
2
3
4
5
6
7
8
const detectScrollToBottom = () => {
const { clientHeight, scrollHeight, ScrollTop } = document.querySelector('#el');
if(clientHeight + ScrollTop + 1 >= scrollHeight) {
console.log('已滑動至底部')
}
}

document.querySelector('#el').addEventListener('scroll', () => detectScrollToBottom());

或是多加一些 range 可以讓元素快到底部時就觸發回函

但是… 這樣又會有一些問題

因為加上了緩衝的range就有可能讓回函重複觸發

所以

為了避免事件重複觸發而不斷請求資料
可以加上一個 isLoading 的 Flag 來防呆
如果已經偵測到底部並請求資料時
就必須等到 timeout 或資料獲取完畢才能夠再觸發請求的回函

本文作者: David Huang
本文地址https://davidblog.github.io/2023/06/17/上拉加載/

0%