scroll-view分页加载

一、核心原理

分页加载的核心逻辑是:当scroll-view滚动到底部时,触发数据请求,获取下一页数据并追加到现有列表中。关键需实现两个核心点:

  • 准确监听scroll-view的滚动到底部事件

  • 管理分页状态(当前页码、是否加载中、是否已无更多数据),避免重复请求或无效请求

二、基础配置(scroll-view属性)

需为scroll-view设置以下关键属性,确保滚动监听正常:

|--------------------------|-----------------|-------|---------------------------------------------|
| lower-threshold | Number | | 距底部/右边多远时(单位px)触发scrolltolower事件,默认50px |
| scrolltolower | EventHandle | | 滚动到底部/右边时触发的事件(核心事件) |
| style="height: 具体高度" | String | | 必须给scroll-view设置固定高度,否则无法正常滚动和触发事件 |

三、完整代码实现

以下是可直接复用的完整示例,包含页面结构、样式、逻辑(以获取列表数据为例):

3.1 页面结构(template)

复制代码
<template>
  <view class="container">
    <!-- 分页列表容器:scroll-view -->
    <scroll-view
      class="scroll-list"
      scroll-y
      scroll-with-animation
      lower-threshold="100"
      @scrolltolower="loadMoreData"
    >
      <!-- 列表项 -->
      <view class="list-item" v-for="(item, index) in listData" :key="index">
        {{ item.title }}
      </view>
      
      <!-- 加载状态提示 -->
      <view class="load-status">
        {{ loadStatusText }}
      </view>
    </scroll-view>
  </view>
</template>

3.2 样式(style)

复制代码
<style scoped>
.container {
  width: 100%;
  height: 100vh; /* 占满整个视口高度 */
}

/* 关键:scroll-view必须设置固定高度 */
.scroll-list {
  width: 100%;
  height: 100%;
  padding: 10rpx;
  box-sizing: border-box;
}

.list-item {
  width: 100%;
  height: 200rpx;
  line-height: 200rpx;
  text-align: center;
  border: 1rpx solid #eee;
  border-radius: 10rpx;
  margin-bottom: 10rpx;
}

.load-status {
  text-align: center;
  padding: 20rpx 0;
  color: #999;
  font-size: 24rpx;
}
</style>

3.3 逻辑(script)

复制代码
<script>
export default {
  data() {
    return {
      listData: [], // 列表数据
      pageNum: 1, // 当前页码(默认从1开始)
      pageSize: 10, // 每页条数
      isLoading: false, // 是否正在加载中(防止重复请求)
      hasMore: true, // 是否还有更多数据
      loadStatusText: "下拉加载更多" // 加载状态提示文本
    };
  },
  onLoad() {
    // 页面加载时,初始化第一页数据
    this.initData();
  },
  methods: {
    // 初始化第一页数据
    async initData() {
      this.pageNum = 1; // 重置页码
      this.listData = []; // 清空列表
      this.hasMore = true; // 重置是否有更多数据
      await this.getListData(); // 请求数据
    },
    
    // 核心:请求列表数据
    async getListData() {
      // 防止重复请求
      if (this.isLoading) return;
      
      // 标记为加载中
      this.isLoading = true;
      this.loadStatusText = "加载中...";
      
      try {
        // 1. 发起请求(替换为你的真实接口地址)
        const res = await uni.request({
          url: "https://api.example.com/list", // 示例接口
          method: "GET",
          data: {
            pageNum: this.pageNum,
            pageSize: this.pageSize
          }
        });
        
        // 2. 处理接口返回数据(根据实际接口格式调整)
        const { code, data, msg } = res.data;
        if (code === 200) {
          const currentPageData = data.list; // 当前页数据
          const total = data.total; // 总数据条数
          
          // 3. 追加数据(第一页直接赋值,后续页追加)
          if (this.pageNum === 1) {
            this.listData = currentPageData;
          } else {
            this.listData = [...this.listData, ...currentPageData];
          }
          
          // 4. 判断是否还有更多数据(当前累计条数 >= 总条数,则无更多)
          if (this.listData.length >= total) {
            this.hasMore = false;
            this.loadStatusText = "已加载全部数据";
          } else {
            this.loadStatusText = "下拉加载更多";
          }
        } else {
          uni.showToast({ title: msg || "请求失败", icon: "none" });
        }
      } catch (error) {
        console.error("列表数据请求失败:", error);
        uni.showToast({ title: "网络异常", icon: "none" });
      } finally {
        // 无论成功失败,都标记为加载完成
        this.isLoading = false;
      }
    },
    
    // 滚动到底部触发:加载下一页
    loadMoreData() {
      // 若没有更多数据或正在加载中,不触发请求
      if (!this.hasMore || this.isLoading) return;
      
      // 页码+1,请求下一页
      this.pageNum++;
      this.getListData();
    }
  }
};
</script>

四、关键注意事项

1. scroll-view必须设置固定高度:这是最容易踩坑的点!如果不设置固定高度,scroll-view会被内容撑开,无法触发滚动事件。可通过父容器定高、scroll-view设置height: 100%继承,或直接设置height: xxxpx实现。

2. 防止重复请求:通过isLoading状态控制,请求发起时设为true,请求完成(无论成功失败)设为false,避免滚动到底部时多次触发请求。

3. 处理无更多数据场景:通过hasMore状态和总条数判断,当已加载数据等于总条数时,设置hasMore为false,不再触发后续请求,并更新提示文本。

4. lower-threshold合理设置:默认50px,可根据需求调整。值太小可能导致用户快速滚动时漏触发,值太大可能提前触发加载。

5. 下拉刷新扩展:如果需要下拉刷新功能,可在scroll-view上添加@scrolltoupper事件(滚动到顶部),结合下拉刷新动画实现,逻辑与分页加载类似(重置页码,重新请求第一页)。

6. 数据缓存与重置:如果页面有筛选、搜索等功能,触发筛选后需调用initData方法,重置页码、清空列表,重新加载第一页数据。

五、常见问题排查

5.1 滚动到底部不触发scrolltolower事件?

  • 检查scroll-view是否设置了固定高度

  • 检查scroll-y是否设为true(纵向滚动必须开启)

  • 检查内容是否足够长(内容高度需超过scroll-view高度才能滚动)

5.2 多次触发加载请求?

  • 确保isLoading状态控制有效,请求发起时设为true,完成后设为false

  • 适当增大lower-threshold值,避免快速滚动时连续触发

5.3 数据加载后页面不滚动?

检查是否在数据更新后触发了不必要的DOM重绘,或scroll-view的高度设置被动态改变。可通过uni.createSelectorQuery()获取scroll-view高度,确认是否正常。

相关推荐
beckyye2 小时前
ant design vue Table根据数据合并单元格
前端·antd
布列瑟农的星空2 小时前
还在手动翻译国际化词条?AST解析+AI翻译实现一键替换
前端·后端·ai编程
土豆12502 小时前
Rust 错误处理完全指南:从入门到精通
前端·rust·编程语言
QT 小鲜肉3 小时前
【Linux命令大全】001.文件管理之mmove命令(实操篇)
linux·服务器·前端·chrome·笔记
前端开发爱好者3 小时前
VSCode 重磅更新!要收费了?
前端·javascript·visual studio code
烛阴3 小时前
C# 正则表达式(4):分支与回溯引用
前端·正则表达式·c#
wuhen_n4 小时前
LeetCode -- 1:两数之和(简单)
javascript·算法·leetcode·职场和发展
曹牧4 小时前
Java:Assert.isTrue()
java·前端·数据库
脾气有点小暴4 小时前
uniapp自定义头部导航
前端·uni-app