鸿蒙应用开发实战:轻松实现列表上拉加载更多

这是一个使用鸿蒙技术开发的本地原生记账应用,非常适合大家用来练手。相关源码已上传至 Github,点击此处查看项目。欢迎大家交流、指正,也欢迎提交 PR。

一、引言

在移动应用开发中,列表的"上拉加载更多"是一个极其常见的交互模式。当用户滑动列表到底部时,自动加载下一页数据,能够极大地提升用户体验。在鸿蒙(HarmonyOS)应用开发中,实现这一效果同样非常便捷。

本文将带你从零开始,手把手实现一个带有"正在加载中"提示的上拉加载效果,让你快速掌握其核心实现原理。

二、效果预览与核心思路

我们先来看一下最终要实现的效果:当列表滑动到底部时,底部会显示一个"正在加载中..."的提示,模拟网络请求完成后,新的数据被追加到列表中,加载提示消失。

实现这个效果,主要依赖以下几个核心点:

  1. List 组件:作为列表的容器,提供滚动和布局能力。
  2. onReachEnd 事件 :List 组件提供的一个回调事件,当列表滚动到底部时自动触发。
  3. 状态管理 :通过一个 @State 变量来控制"加载中"状态的显示与隐藏。
  4. 数据模拟 :使用 setTimeout 模拟异步网络请求。

三、代码实现与详解

下面我们直接进入代码环节,看看如何一步步构建这个功能。

3.1 定义数据与状态

首先,我们需要定义列表的数据源和一个用于标识加载状态的状态变量。

typescript 复制代码
@Entry
@Component
struct PullUpLoadDemo {
  // 列表数据源
  @State private listData: string[] = [];
  // 是否正在加载中
  @State private isLoading: boolean = false;

  aboutToAppear() {
    // 初始化时加载第一页数据
    this.loadMoreData();
  }

  // 模拟加载更多数据
  loadMoreData() {
    // 模拟网络请求延迟
    setTimeout(() => {
      // 生成新的数据项
      let newData: string[] = [];
      for (let i = 0; i < 10; i++) {
        newData.push(`列表项 ${this.listData.length + i + 1}`);
      }
      // 将新数据追加到现有数据中
      this.listData = [...this.listData, ...newData];
      // 加载完成,更新状态
      this.isLoading = false;
    }, 1500); // 模拟1.5秒的网络延迟
  }

  build() {
    // ... 构建UI
  }
}

3.2 构建列表 UI

接下来,在 build 方法中构建我们的列表 UI。关键在于 List 组件的 onReachEnd 事件。

typescript 复制代码
  build() {
    Column() {
      List() {
        // 1. 使用 ForEach 渲染数据列表
        ForEach(this.listData, (item: string) => {
          ListItem() {
            Text(item)
              .width('100%')
              .height(80)
              .fontSize(18)
              .textAlign(TextAlign.Center)
              .backgroundColor(Color.White)
              .borderRadius(10)
              .margin({ top: 10 })
          }
        }, (item: string) => item)

        // 2. 在列表末尾添加"加载中"提示项
        if (this.isLoading) {
          ListItem() {
            Row() {
              LoadingProgress()
                .width(24)
                .height(24)
                .margin({ right: 10 })
              Text('正在加载中...')
                .fontSize(16)
                .fontColor('#666')
            }
            .justifyContent(FlexAlign.Center)
            .width('100%')
            .height(60)
          }
        }
      }
      .width('100%')
      .height('100%')
      .backgroundColor('#F5F5F5')
      // 3. 核心:监听列表滚动到底部事件
      .onReachEnd(() => {
        // 如果当前正在加载,则直接返回,避免重复请求
        if (this.isLoading) {
          return;
        }
        // 设置加载状态为 true,显示加载提示
        this.isLoading = true;
        // 调用加载数据的方法
        this.loadMoreData();
      })
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }

四、完整代码示例

为了方便你直接运行和测试,这里提供完整的代码片段。

typescript 复制代码
@Entry
@Component
struct PullUpLoadDemo {
  @State private listData: string[] = [];
  @State private isLoading: boolean = false;

  aboutToAppear() {
    this.loadMoreData();
  }

  loadMoreData() {
    setTimeout(() => {
      let newData: string[] = [];
      for (let i = 0; i < 10; i++) {
        newData.push(`列表项 ${this.listData.length + i + 1}`);
      }
      this.listData = [...this.listData, ...newData];
      this.isLoading = false;
    }, 1500);
  }

  build() {
    Column() {
      List() {
        ForEach(this.listData, (item: string) => {
          ListItem() {
            Text(item)
              .width('100%')
              .height(80)
              .fontSize(18)
              .textAlign(TextAlign.Center)
              .backgroundColor(Color.White)
              .borderRadius(10)
              .margin({ top: 10 })
          }
        }, (item: string) => item)

        if (this.isLoading) {
          ListItem() {
            Row() {
              LoadingProgress()
                .width(24)
                .height(24)
                .margin({ right: 10 })
              Text('正在加载中...')
                .fontSize(16)
                .fontColor('#666')
            }
            .justifyContent(FlexAlign.Center)
            .width('100%')
            .height(60)
          }
        }
      }
      .width('100%')
      .height('100%')
      .backgroundColor('#F5F5F5')
      .onReachEnd(() => {
        if (this.isLoading) {
          return;
        }
        this.isLoading = true;
        this.loadMoreData();
      })
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }
}

运行效果:

五、总结

通过以上步骤,我们成功地在鸿蒙应用中实现了列表的上拉加载更多功能。核心逻辑可以总结为:

  1. 监听事件 :利用 List 组件的 onReachEnd 事件监听滚动到底部。
  2. 状态控制 :通过 isLoading 状态变量防止重复加载,并控制加载提示的显示。
  3. 数据追加:在模拟的异步请求完成后,将新数据追加到原有数据源中。

这个模式非常通用,你可以轻松地将它应用到实际项目中的分页数据加载场景。希望这篇教程对你有所帮助!

相关推荐
用户461169657283 分钟前
网站 HTTPS 不稳定?证书排查指南
前端
n876514 分钟前
Playwright Java WEB UI 自动化实现框架与逻辑
java·前端·ui
keyipatience16 分钟前
TypeScript学习(1)
前端·javascript·学习·typescript·html·css3
xifangge20251 小时前
基于 JavaScript 实现 CNC 数控切削参数与螺纹公差纯前端核算引擎
开发语言·前端·javascript
wangruofeng1 小时前
2026 Web 技术选型指南,AI 时代如何选择适合项目的技术栈
前端·aigc·ai编程
honkun61 小时前
vue 表格组件 vxe-table 修改滚动条样式,修改滚动条样式,统一宽度、颜色与自动隐藏
前端·javascript·vue.js
爱勇宝2 小时前
研究数字孪生的这半年,做了个 Demo,也有了一些新想法
前端·程序员
不可能片场2 小时前
工程实践 一个缓存把选片从十分钟压到一分钟
前端·electron
前端小万2 小时前
探索副业五个月,最终以放弃告终
前端·后端·面试
FRing032 小时前
JavaScript入门到精通二十四(正则表达式、元字符、修饰符)
开发语言·前端·javascript·正则表达式