鸿蒙开发深入浅出03(封装通用LazyForEach实现懒加载)

news/2025/2/25 14:53:20

鸿蒙开发深入浅出03(封装通用LazyForEach实现懒加载)

  • 1、效果展示
  • 2、ets/models/BasicDataSource.ets
  • 3、ets/models/HomeData.ets
  • 4、ets/api/home.ets
  • 5、ets/pages/Home.ets
  • 6、ets/views/Home/SwiperLayout.ets
  • 7、后端代码

1、效果展示

在这里插入图片描述

在这里插入图片描述

2、ets/models/BasicDataSource.ets

// BasicDataSource实现了IDataSource接口,用于管理listener监听,以及通知LazyForEach数据更新
// https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-rendering-control-lazyforeach-V5#stringdata%E7%B1%BB%E5%9E%8B%E6%95%B0%E7%BB%84%E7%9A%84basicdatasource%E4%BB%A3%E7%A0%81
export default class BasicDataSource<T> implements IDataSource {
  // 内部用来触发UI更新的对象
  private listeners: DataChangeListener[] = [];
  // 管理的数据
  private list: T[] = [];

  // 返回数据总长度
  public totalCount(): number {
    return this.list.length;
  }

  // 读取对应下标的数据
  public getData(index: number): T {
    return this.list[index];
  }

  // 保存单个数据
  public setData(item: T) {
    // 只会更新数据,不会更新UI
    this.list.push(item);
    // 更新UI操作
    this.notifyDataAdd(this.list.length - 1);
  }

  // 更新所有列表数据
  public setList(list: T[]) {
    this.list = list;
    // 全部通知修改
    this.notifyDataReload();
  }

  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.info('add listener');
      this.listeners.push(listener);
    }
  }

  // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      console.info('remove listener');
      this.listeners.splice(pos, 1);
    }
  }

  // 通知LazyForEach组件需要重载所有子组件
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    })
  }

  // 通知LazyForEach组件需要在index对应索引处添加子组件
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
      // 写法2:listener.onDatasetChange([{type: DataOperationType.ADD, index: index}]);
    })
  }

  // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index);
      // 写法2:listener.onDatasetChange([{type: DataOperationType.CHANGE, index: index}]);
    })
  }

  // 通知LazyForEach组件需要在index对应索引处删除该子组件
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index);
      // 写法2:listener.onDatasetChange([{type: DataOperationType.DELETE, index: index}]);
    })
  }

  // 通知LazyForEach组件将from索引和to索引处的子组件进行交换
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMove(from, to);
      // 写法2:listener.onDatasetChange(
      //         [{type: DataOperationType.EXCHANGE, index: {start: from, end: to}}]);
    })
  }

  notifyDatasetChange(operations: DataOperation[]): void {
    this.listeners.forEach(listener => {
      listener.onDatasetChange(operations);
    })
  }
}

3、ets/models/HomeData.ets

注意因为我们这个模块使用了BasicDataSource.ets,所以从鸿蒙开发深入浅出02(封装Axios请求、渲染Swiper)需改为ets后缀。

import BasicDataSource from './BasicDataSource';

@Observed
export class BasicListDataSource<T> extends BasicDataSource<T> {
  lists: T[] = [];
}

export interface IHomeData {
  "bannerList": IBannerList
  "navList": INavList
  "tileList": ITileList
  "planList": IPlanList
  "adPicture": string
}

// 计划列表类型
export interface IPlanItem {
  "id": number
  "imageURL": string
}

export type IPlanList = IPlanItem[]

// 瓷片列表类型
export interface ITileItem {
  "id": number
  "imageURL": string
  "title": string
  "sub_title": string
}

export type ITileList = ITileItem[]

// 导航列表类型
export interface INavItem {
  "id": number
  "title": string
  "imageURL": string
}

export type INavList = INavItem[]

// 轮播图类型
export interface IBannerItem {
  "id": number
  "name": string
  "imageURL": string
}

export type IBannerList = IBannerItem[]

4、ets/api/home.ets

同 3 所述,home.ts 也需改为 ets 结尾,并添加返回类型。

import { http } from '../utils/http'
import type { IHomeData } from '../models/HomeData'

// 获取页面数据
export const getHomeDataApi = (): Promise<IHomeData> => {
  return http.get<IHomeData>('/home/info')
}

5、ets/pages/Home.ets

import { getHomeDataApi } from "../api/home"
import { BasicListDataSource, IBannerItem, IBannerList } from "../models/HomeData"
import SwiperLayout from '../views/Home/SwiperLayout'

/**
 * MyHouseApplication #项目的名称
 * Home.ets #文件名称
 * Created by zhong ON 2025/2/23 #作者及添加日期
 */
@Component
export default struct Home {
  @State bannerList: BasicListDataSource<IBannerItem> = new BasicListDataSource();
  // 获取首页数据的函数
  getHomeData = async () => {
    const result = await getHomeDataApi();
    this.bannerList.setList(result.bannerList);
  }

  // 生命周期函数,初始化页面时触发
  aboutToAppear(): void {
    this.getHomeData();
  }

  build() {

    Scroll() {
      Column() {
        SwiperLayout({ bannerList: this.bannerList });
      }.width('100%')

    }
    .width('100%')
    .height('100%')
    .scrollBar(BarState.Off)
    .align(Alignment.TopStart)
  }
}

6、ets/views/Home/SwiperLayout.ets

/**
 * MyHouseApplication #项目的名称
 * SwiperLayout.ets #文件名称
 * Created by zhong ON 2025/2/23 #作者及添加日期
 */
import { IBannerItem, BasicListDataSource } from "../../models/HomeData"


@Component
export default struct SwiperLayout {
  @ObjectLink bannerList: BasicListDataSource<IBannerItem>;

  build() {
    Swiper() {
      LazyForEach(this.bannerList, (banner: IBannerItem) => {
        Image(banner.imageURL).width('100%')
          .height('100%')
          .objectFit(ImageFit.Fill)
      }, (banner: IBannerItem) => banner.id + '')
    }.width('100%')
    .height(211 - 36)
    .indicator(
      new DotIndicator()
        .color($r('app.color.indicator_color'))
        .selectedColor($r('app.color.indicator_active_color'))
    )
  }
}

7、后端代码

双击 zufangBackend-windows-amd64.exe 运行

在这里插入图片描述


http://www.niftyadmin.cn/n/5865627.html

相关文章

bind()函数的概念和使用案例

在计算机网络编程中&#xff0c;bind() 是一个用于将一个套接字&#xff08;socket&#xff09;与一个特定的网络地址和端口号关联起来的系统调用。这个函数通常在服务器端编程中使用&#xff0c;用于指定服务器将监听哪个网络接口和端口号上的连接请求。 bind() 的概念 套接…

2007年诺基亚内部对iPhone的竞争分析报告

2007年iPhone发布后&#xff0c;诺基亚内部至少有9名员工指出其触屏界面、互联网整合能力将颠覆市场&#xff0c;并建议开发同类产品&#xff0c;但高管因当时占据全球50%市场份额而轻视威胁&#xff0c;认为苹果的高价和虚拟键盘会限制其普及。 诺基亚虽然意识到需推出触屏手机…

angular日历

说明: 写一个简单的日历功能 效果图&#xff1a; step1:C:\Users\Administrator\WebstormProjects\untitled4\src\app\calendar\calendar.component.ts import { Component, signal } from angular/core; import { CommonModule } from angular/common; import { MatButtonM…

中国的Cursor! 字节跳动推出Trae,开放Windows版(附资源),开发自己的网站,内置 GPT-4o 强大Al模型!

Trae是什么 Trae 是字节跳动推出的免费 AI IDE&#xff0c;通过 AI 技术提升开发效率。支持中文&#xff0c;集成了 Claude 3.5 和 GPT-4 等主流 AI 模型&#xff0c;完全免费使用。Trae 的主要功能包括 Builder 模式和 Chat 模式&#xff0c;其中 Builder 模式可帮助开发者从…

PostgreSQL数据库之pg_dump使用

目录 前言 1. 基础用法 1.1 备份整个数据库到 SQL 文件 2. 备份选项 2.1 仅备份结构&#xff08;不包含数据&#xff09; 2.2 仅备份数据&#xff08;不包含表结构&#xff09; 2.3 备份特定表 2.4 排除特定表 2.5 备份为自定义格式&#xff08;支持压缩和快速恢复&am…

将Ubuntu操作系统的安装源设置为阿里云

在使用Ubuntu操作系统时,默认的软件源通常是国外的仓库,这可能会导致软件安装和更新速度较慢。为了提高下载速度和稳定性,我们可以将Ubuntu的安装源设置为阿里云镜像源。以下是详细步骤: 一、准备工作 在开始之前,请确保您的Ubuntu系统可以正常上网,并且您拥有管理员权…

日常知识点之刷题一

1&#xff1a;流浪地球 0~n-1个发动机&#xff0c;计划启动m次&#xff0c;求最后启动的发动机的个数。 以及发动机的编号。&#xff08;模拟过程&#xff0c;每次手动启动的机器对应时间向两边扩散&#xff09; //输入每个启动的时间和编号 void test_liulang() {int n, m;ci…

数据库(MySQL)二

MySQL 六、MySQL索引视图6.1 索引底层原理6.1.1 索引hash算法6.1.2 索引二叉树算法6.1.3 索引平衡二叉树算法6.1.4 索引BTREE树算法6.1.5 普通SQL全表扫描过程 6.2 索引分类6.2.1 按数据结构层次分类6.2.2 按字段数量层次分类6.2.3 按功能逻辑层次分类&#xff08;面试题&#…