HarmonyOS鸿蒙Next中Sections多列混排

发布于 1周前 作者 nodeper 来自 鸿蒙OS

HarmonyOS鸿蒙Next中Sections多列混排

学习点

  • @Reusable 装饰器
  • WaterFlow瀑布流容器
  • 模块组件
  • 代码讲解

@Reusable 装饰器使用场景

@Reusable 是一个在 HarmonyOS ArkTS 中使用的装饰器,主要用于自定义组件的复用。从 API version 10 开始,@Reusable 装饰器得到了支持。它的主要功能是当一个标记为 @Reusable 的自定义组件从组件树上被移除时,该组件及其对应的 JSView 对象会被放入复用缓存中。这样,在后续需要创建新的自定义组件节点时,可以复用缓存区中的节点,从而节约组件重新创建的时间。

  • 列表滚动:当应用需要展示大量数据的列表,并且用户进行滚动操作时,频繁创建和销毁列表项的视图可能导致卡顿和性能问题。在这种情况下,使用列表组件的组件复用机制可以重用已经创建的列表项视图,提高滚动的流畅度。
  • 动态布局更新:如果应用中的界面需要频繁地进行布局更新,例如根据用户的操作或数据变化动态改变视图结构和样式,重复创建和销毁视图可能导致频繁的布局计算,影响帧率。在这种情况下,使用组件复用可以避免不必要的视图创建和布局计算,提高性能。
  • 频繁创建和销毁数据项的视图场景下。使用组件复用可以重用已创建的视图,只更新数据的内容,减少视图的创建和销毁,能有效提高性能。

使用场景和限制条件 @Reusable 装饰器主要用于自定义组件,它只能与 @Component 结合使用。这意味着你可以在自定义组件的定义中使用 @Reusable 来标记那些需要被复用的组件。尝试过@Reusable 装饰器和@ComponentV2结合使用,显示不出来效果,可能目前@Reusable 装饰器目前还不支持@ComponentV2结合使用。

WaterFlow使用场景

WaterFlow滑动场景存在FlowItem及其子组件的频繁创建和销毁,可以将FlowItem中的组件封装成自定义组件,并使用@Reusable装饰器修饰,使其具备组件复用能力。

WaterFlow({ scroller: this.scroller, sections: this.sections }) {
  LazyForEach(this.dataSource, (item: Record<string, Object>) => {
    FlowItem() {
      ReusableFlowItem({ item: item, imgPath: this.imgPath })
    }
  }, (item: string) => item)
}
[@Reusable](/user/Reusable)
[@Component](/user/Component)
struct ReusableFlowItem {
 @State item: Record<string, Object> = {};
 public imgPath: string = ''

 aboutToReuse(params: Record<string, Object>) {
   this.item = params.item as Record<string, Object>;
 }
}

SectionsComponent模块组件实现

  1. 右击项目名称 -> 新建 -> 模块 -> Static Library -> Module name: SectionsComponent
  2. 右击SectionsComponent模块ets目录 -> 新建 -> 目录 -> components
  3. 创建SectionsComponent组件,并export导出
  4. 右击SectionsComponent模块ets目录 -> 新建 -> 目录 -> model
  5. 创建WaterFlowDataSource类,实现IDataSource接口,并export导出
  6. 在SectionsComponent模块根目录下Index.ets文件,导出模块组件,提供给外部使用
export { SectionsComponent } from './src/main/ets/components/SectionsComponent';

代码讲解

1. 下图就是模块组件的代码结构图

模块组件的代码结构图

2. 注意模块组件里oh-package.json5文件里的name

oh-package.json5文件里的name

3. 在entry模块下oh-package.json5引用模块组件

在entry模块下oh-package.json5引用模块组件

4. 在Index.ets主界面引用模块组件

import { SectionsComponent } from 'sectionslibrary';

Column() {
  SectionsComponent({imgPath: this.imgPath, dataArray: this.dataArray})
}

5. WaterFlowDataSource数据源类讲解

export class WaterFlowDataSource implements IDataSource {
 private dataArray: Record<string, Object>[] = []
 private listeners: DataChangeListener[] = []

 /**
  * 构造函数
  * @param dataArray
  */
 constructor(dataArray: Record<string, Object>[]) {
   this.dataArray = dataArray
 }

 /**
  * 获得数据总数
  * @returns
  */
 totalCount(): number {
   return this.dataArray.length;
 }

 /**
  * 获取索引值index对应的数据
  * @param index
  * @returns
  */
 getData(index: number): Record<string, Object> {
   return this.dataArray[index];
 }

 /**
  * 注册数据改变的监听器
  * @param listener
  */
 registerDataChangeListener(listener: DataChangeListener): void {
   if (this.listeners.indexOf(listener) < 0) {
     this.listeners.push(listener)
   }
 }

 /**
  * 注销数据改变的监听器
  * @param listener
  */
 unregisterDataChangeListener(listener: DataChangeListener): void {
   const pos = this.listeners.indexOf(listener);
   if (pos >= 0) {
     this.listeners.splice(pos, 1);
   }
 }

 /**
  * 追加数据
  */
 public addLastItem(): void {
   // start:指定修改开始的位置(索引)。
   // deleteCount(可选):一个整数,表示要移除的数组元素的个数。如果省略,则移除从start位置到数组末尾的所有元素。
   // ...items(可选):要添加进数组的新元素,从start位置开始。如果没有指定,则只删除元素。
   // 在索引数组长度的位置插入当前数组长度,不删除任何元素。
   let obj: Record<string, Object> = { 'key': this.dataArray.length, 'value': `${(this.dataArray.length) % 4}.png` }
   this.dataArray.splice(this.dataArray.length, 0, obj );
   this.notifyDataAdd(this.dataArray.length - 1);
 }

 // 通知数据有添加
 notifyDataAdd(index: number): void {
   this.listeners.forEach(listener => {
     listener.onDataAdd(index);
   })
 }
}

6. SectionsComponent组件讲解

使用@Reusable 装饰器标记被复用的组件

[@Reusable](/user/Reusable)
[@Component](/user/Component)
struct ReusableFlowItem {
 @State item: Record<string, Object> = {};
 public imgPath: string = ''

 aboutToReuse(params: Record<string, Object>) {
   this.item = params.item as Record<string, Object>;
 }

 build() {
   ...
 }
}

导出WaterFlow组件

[@Component](/user/Component)
export struct SectionsComponent {
 public imgPath: string = '';
 @Link dataArray: Record<string, Object>[];

 build() {
   Column({ space: 0 }) {
     WaterFlow({ scroller: this.scroller, sections: this.sections }) {
       LazyForEach(this.dataSource, (item: Record<string, Object>) => {
         FlowItem() {
           ReusableFlowItem({ item: item, imgPath: this.imgPath })
         }
       }, (item: string) => item)
     }
   }
 }

总结

通过使用@Reusable 装饰器标记复用组件,结合LazyForEach懒加载,丝滑感觉就出来了,想尝试这丝滑感觉的,可以在源码仓库或附件里下载源代码体验一下,本项目创建时选择的API13,可以通过本地模拟器上运行体验,开发这个Sample时,使用的开发工具是DevEco Studio 5.0.3 Beta2,里面集成了DeepSeek,大家也可以下载最新版本体验一下。

源码仓库:https://atomgit.com/next_project/SectionsWaterFlowSample

源码仓库截图

源码仓库截图


更多关于HarmonyOS鸿蒙Next中Sections多列混排的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS鸿蒙Next中,Sections多列混排是一种用于实现复杂布局的组件。它允许开发者在同一页面中创建多个列,并且每列可以包含不同类型的内容,如文本、图片、按钮等。Sections组件通过灵活的布局方式,能够适应不同屏幕尺寸和设备类型,确保用户界面的一致性和美观性。

Sections多列混排的核心是通过SectionColumn组件来实现的。Section用于定义一个大块的内容区域,而Column则用于在Section内创建多个列。开发者可以通过设置Column的宽度、间距、对齐方式等属性,来调整每列的布局效果。

在鸿蒙Next中,Sections多列混排还支持响应式布局。开发者可以通过设置不同的断点(breakpoints),来定义在不同屏幕尺寸下每列的显示方式。例如,在大屏幕设备上,可以显示多列内容;而在小屏幕设备上,可以自动调整为单列显示,以确保内容的可读性和用户体验。

此外,Sections多列混排还支持动态内容更新。开发者可以通过数据绑定机制,将数据源与SectionColumn组件进行绑定,实现内容的动态加载和更新。这使得Sections组件在处理大量数据或需要频繁更新的场景下,依然能够保持高效的性能。

总的来说,HarmonyOS鸿蒙Next中的Sections多列混排组件,为开发者提供了一种灵活、高效的布局方式,能够满足不同场景下的界面设计需求。

更多关于HarmonyOS鸿蒙Next中Sections多列混排的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,Sections多列混排是一种灵活的布局方式,允许开发者在一个页面中实现多列内容的动态排列。通过使用ListContainerGridLayout等组件,开发者可以轻松实现不同列数的混排效果。Sections可以帮助将内容划分为多个独立的部分,每个部分可以拥有不同的列数和样式,从而提升用户体验。开发者可以通过调整layoutConfigitemProvider等参数,灵活控制每列的显示内容和布局方式,实现复杂界面的高效构建。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!