向上滚动加载数据

8/15/2024 通用组件

# 模版代码

<div @scroll="onScroll" ref="scrollTopLoadingDataRef" id="scroll-top-loading-data">
    <div v-if="showLoading" class="loading">{{ loadingText }}</div>
    <div class="box" :key="item" v-for="item in boxList">{{ item }}</div>
</div>
1
2
3
4

# 模拟网络请求

let idx = 0;
const getBoxes = () => {
  return new Promise((resolve) => {
    let result = []
    setTimeout(() => {
      // 模拟没有更多数据
      if (idx > 10) {
        resolve(result)
        return
      }
      // 填充数据
      for (let i = idx + 9; i >= idx; i--) {
        result.push(i)
      }
      // 更新索引记录
      idx = idx + 10
      resolve(result)
    }, 2000)
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 关键代码

const onScroll = async (e) => {
    // 查找目标元素
    let scrollTopLoadingDataRef = document.querySelector("#scroll-top-loading-data")
    if (e.target.scrollTop === 0 && !showLoading) {
        console.log("开始加载数据。。。")
        // 记录当前滚动盒子高度
        beforeScrollHeight = scrollTopLoadingDataRef.scrollHeight
        // 开启加载提示
        showLoading = true
        try {
            const result = await this.getBoxes()
            console.log("result", result)
            if (result.length === 0) {
                loadingText = '没有更多数据了'
                // 如果没有数据,不应该修改 scrollTop 属性,否则又会立即触发 onScroll事件,导致进入死循环
                return
            }
            boxList.unshift(...result)
        } catch (e) {
            console.log(e)
        } finally {
            // 无论如何最总都会执行
            showLoading = false
        }
        
        // 设置当前滚动盒子距离顶部偏移 =  当前总滚动盒子高度 - 未添加元素之前滚动盒子高度
        scrollTopLoadingDataRef.scrollTop = scrollTopLoadingDataRef.scrollHeight - beforeScrollHeight
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29