当前位置: 首页 > news >正文

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

鸿蒙开发深入浅出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

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'))
    )
  }
}

相关文章:

  • MySQL 数据库基础
  • Ryu控制器:L2交换功能实现案例
  • 帆软report
  • 使用GPU训练模型
  • js数据类型检测
  • Linux 常见面试题汇总
  • Baklib一站式企业知识库搭建指南
  • Deepseek首页实现 HTML
  • 连接Sql Server时报错无法通过使用安全套接字层加密与 SQL Server 建立安全连接
  • 通俗易懂的浏览器事件循环指南(含async/await)
  • Linux提权之计划任务反弹shell提权(十一)
  • 【Viewer.js】vue3封装图片查看器
  • 【时时三省】(C语言基础)结构化程序设计方法
  • 二:前端发送POST请求,后端获取数据
  • Java并发 ThreadLocal 原理(详解)
  • c++中,什么时候应该使用mutable关键字?
  • Bash Shell控制台终端命令合集
  • C语言番外篇(3)------------>break、continue
  • 论文笔记:Autonomy-of-Experts Model
  • watchEffect 里有响应式依赖时并没有自动追踪
  • 国家发改委答澎湃:力争6月底前下达2025年两重建设和中央预算内投资全部项目清单
  • 人民时评:投资于人,促高质量充分就业
  • 格力电器去年净利增长一成:消费电器营收下滑4%,一季度净利增长26%
  • 五矿地产:今年要确保债务“不爆雷”、交付“不烂尾”
  • 财政部、证监会:加强对会计师事务所从事证券服务业务的全流程监管
  • 政治局会议:要提高中低收入群体收入,设立服务消费与养老再贷款