鸿蒙开发中的List组件详解

目录

引言

1.List组件基础

2.List接口参数

1.space

2.initialIndex

3.scroller

3.ListView的属性

1.listDirection

2.lanes

3.divider

4.scrollBar

4.布局与约束

5.ListItem生命周期

1.使用ForEach创建ListItem

2.使用LazyForEach创建ListItem

3.使用Repeat创建ListItem

1.使用virtualScroll

2.不使用virtualScroll

6.List的使用场景

[1. 最简单的List](#1. 最简单的List)

[2. 自定义组件](#2. 自定义组件)

[3. 滚动控制](#3. 滚动控制)

高级特性

[1. 分组列表](#1. 分组列表)

[2. 懒加载](#2. 懒加载)

[3. 下拉刷新与上拉加载](#3. 下拉刷新与上拉加载)

性能优化技巧

常见问题解决

结语


引言

在鸿蒙(HarmonyOS)应用开发中,List组件是最常用的UI组件之一,用于展示垂直滚动的列表数据。本文将详细介绍List组件的特性、使用方法以及一些实用技巧。

1.List组件基础

列表是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求(如通讯录、音乐列表、购物清单等)。

List是鸿蒙OS中用于展示垂直滚动列表的容器组件,具有以下特点:

  • 高性能的列表渲染

  • 支持大数据量的流畅滚动

  • 内置多种布局和交互效果

  • 支持分组和多种列表项样式

2.List接口参数

当我们创建 List 的时候,有三个默认可选参数,分别是 space、initialIndex、scroller。

我们分别看看他们的属性。

1.space

space 用来设置子组件主轴方向的间隔。

图1.space属性

2.initialIndex

设置当前 List初次加载的时候,初始 item 的索引值。

图2.修改初次加载显示的数据元素下标

3.scroller

可以滚动组件的控制器。

我们可以调用scroll的相关方法处理List。

例如我们可以通过下面的代码把List滚动到底部

TypeScript 复制代码
          Button("滚动到底部").onClick(()=>{
            this.scroller.scrollEdge(Edge.Bottom)
          })

3.ListView的属性

1.listDirection

设置List组件的排列方向。

listDirection是Axis类型的枚举,定义如下:

declare enum Axis {

Vertical,

Horizontal

}

默认值为Axis.Vertical,方向为纵向。

Axis.Horizontal方向为横向。

2.lanes

设置List组件的布局列数或者行数。

lanes是鸿蒙(HarmonyOS)中List组件的一个重要属性,用于控制列表在水平方向上的布局方式,特别适用于需要多列布局的场景。通过设置lanes属性,可以让List组件中的列表项以网格形式排列,而不是传统的单列垂直排列。

3.divider

设置ListItem分割线样式,默认无分割线。

4.scrollBar

设置滚动条状态。

BarState.AutoAuto:按需显示

BarState.AutoOff:不显示

BarState.AutoOn:常驻显示

4.布局与约束

列表作为一种容器,会自动按其滚动方向排列子组件,向列表中添加组件或从列表中移除组件会重新排列子组件。

如下图所示,在垂直列表中,List按垂直方向自动排列ListItemGroup或ListItem。

ListItemGroup用于列表数据的分组展示,其子组件也是ListItem。ListItem表示单个列表项,可以包含单个子组件。

图3.List、ListItemGroup和ListItem组件关系

5.ListItem生命周期

1.使用ForEach创建ListItem

List组件创建时,所有ListItem将会被创建。显示区域内的ListItem在首帧进行布局,预加载范围内的ListItem在空闲时完成布局。预加载范围之外的ListItem仅创建ListItem自身,ListItem其内部的子组件不会被创建。

当List组件滑动时,进入预加载及显示区域的ListItem将会创建其内部的子组件并完成布局,而滑出预加载及显示区域的ListItem将不会被销毁。

图4.ForEach创建ListItem

2.使用LazyForEach创建ListItem

List组件创建时,显示区域中的ListItem会被创建与布局。预加载范围内的ListItem在空闲时创建与布局,但是不会被挂载到组件树上。预加载范围外的ListItem则不会被创建。

当List组件滑动时,进入预加载及显示区域的ListItem将被创建与布局,创建ListItem过程中,若ListItem内部如果包含@Reusable标记的自定义组件,则会优先从缓存池中复用。滑出预加载及显示区域的ListItem将被销毁,其内部若含@Reusable标记的自定义组件,则会被回收并加入缓存池。

图5.LazyForEach创建ListItem的生命周期

3.使用Repeat创建ListItem

1.使用virtualScroll

List组件创建时,显示区域内的ListItem将被创建和布局。预加载范围内的ListItem在空闲时创建和布局,并且挂载至组件树上。预加载范围外的ListItem则不会被创建。

当List组件滑动时,进入预加载及显示区域的ListItem,将从缓存池中获取ListItem并复用及布局,若缓存池中无ListItem,则会新创建并布局。滑出预加载及显示区域的ListItem会将被回收至缓存池。

图6.Repeat使用virtualScroll创建ListItem的生命周期

2.不使用virtualScroll

List组件创建时,所有ListItem均被创建。显示区域内的ListItem在首帧完成布局,预加载范围内的ListItem在空闲时完成布局。预加载范围外的ListItem不会进行布局。

当List组件滑动时,进入预加载及显示区域的ListItem将进行布局。滑出预加载及显示区域的ListItem不会销毁。

图7.Repeat不使用virtualScroll创建ListItem的生命周期

1.listDirection

1.listDirection

复制代码
// 示例代码:基本List使用
import { List, ListItem } from '@ohos/arkui';

@Entry
@Component
struct MyList {
  private data: string[] = ['苹果', '香蕉', '橙子', '葡萄', '西瓜']

  build() {
    Column() {
      List({ space: 20 }) {
        ForEach(this.data, (item: string) => {
          ListItem() {
            Text(item)
              .fontSize(20)
              .margin({ left: 15 })
          }
        })
      }
      .width('100%')
      .height('100%')
    }
  }
}

6.List的使用场景

1. 最简单的List

在最简单的列表形式中,List静态地创建其列表项ListItem的内容。

当我们ListView的ListItem只有一个组件的时候,我们使用下面的代码即可实现一个简单的列表。

TypeScript 复制代码
@Entry
@Component
struct CityList {
  build() {
    NavDestination(){
      List() {
        ListItem(){
          Text('北京').fontSize(24)
        }
        ListItem(){
          Text('上海').fontSize(24)
        }
        ListItem(){
          Text('杭州').fontSize(24)
        }
      }    .backgroundColor('#FFF1F3F5')
      .alignListItem(ListItemAlign.Center)

    }.title("List实现城市列表")
  }
}

效果图如下:

图8.最简单的List

复制代码
@State private messages: Message[] = [
  { id: 1, content: '你好鸿蒙' },
  { id: 2, content: 'List组件学习' },
  // 更多数据...
];

List() {
  ForEach(this.messages, (item: Message) => {
    ListItem() {
      Text(item.content)
    }
  })
}

2. 自定义组件

因此,如果ListItem是由多个组件元素组成的,则需要将这多个元素组合到一个容器组件内或组成一个自定义组件。

例如我们要实现一个通讯录联系人页面:

图9.联系人列表

如上图所示,联系人列表的列表项中,每个联系人都有头像和名称。此时,需要将Image和Text封装到一个Row容器内。

TypeScript 复制代码
List() {
  ListItem() {
    Row() {
      // app.media.iconE为自定义资源
      Image($r('app.media.iconE'))
        .width(40)
        .height(40)
        .margin(10)

      Text('小明')
        .fontSize(20)
    }
  }

  ListItem() {
    Row() {
      // app.media.iconF为自定义资源
      Image($r('app.media.iconF'))
        .width(40)
        .height(40)
        .margin(10)

      Text('小红')
        .fontSize(20)
    }
  }
}

3. 滚动控制

复制代码
private scroller: Scroller = new Scroller()

List({ scroller: this.scroller }) {
  // 列表内容
}

// 滚动到指定位置
this.scroller.scrollTo({ x: 0, y: 100 })

高级特性

1. 分组列表

复制代码
List() {
  ForEach(this.groupData, (group: Group) => {
    ListItemGroup({ header: this.GroupHeader(group.name) }) {
      ForEach(group.items, (item: Item) => {
        ListItem() {
          Text(item.name)
        }
      })
    }
  })
}

2. 懒加载

复制代码
List() {
  LazyForEach(this.dataSource, (item: Item) => {
    ListItem() {
      Text(item.name)
    }
  })
}

3. 下拉刷新与上拉加载

复制代码
List({ controller: this.listController }) {
  // 列表内容
}
.onRefresh(() => {
  // 下拉刷新逻辑
})
.onReachEnd(() => {
  // 上拉加载更多
})

性能优化技巧

  1. 复用列表项​:确保ListItem的结构尽可能简单,提高复用率

  2. 避免复杂计算​:在列表渲染中避免复杂的计算和频繁的UI更新

  3. 使用LazyForEach​:对于大数据集,使用LazyForEach代替ForEach

  4. 图片懒加载​:列表中的图片使用懒加载技术

常见问题解决

  1. 列表滚动卡顿​:

    • 检查是否有过多的UI更新

    • 确保使用了正确的数据绑定方式

    • 考虑分页加载数据

  2. 列表项点击无响应​:

    • 检查是否添加了.onClick事件

    • 确保没有其他组件遮挡了点击区域

  3. 列表数据显示异常​:

    • 检查数据源是否正确更新

    • 确认ForEach或LazyForEach的key值唯一且稳定

结语

List组件是鸿蒙应用开发中不可或缺的重要组件,掌握其使用方法和优化技巧对于构建流畅的用户界面至关重要。通过本文的介绍,希望您能更高效地使用List组件,为您的鸿蒙应用带来更好的用户体验。

在实际开发中,建议多参考鸿蒙官方文档和示例代码,不断实践和优化您的列表实现。

相关推荐
安防视频中间件/视频资源汇聚平台2 小时前
华为iVS1800接入SVMSPro平台
华为·华为云
心一信息2 小时前
如何通过华为无线控制器添加一个名为yunwei的无线网络
运维·网络·华为
软件开发技术深度爱好者3 小时前
华为仓颉语言的函数初步
华为·仓颉(cangjie)编程语言
AAA修煤气灶刘哥4 小时前
后端仔狂喜!手把手教你用 Java 拿捏华为云 IoTDA,设备上报数据 so easy
后端·物联网·华为
小周同学:4 小时前
【UniApp打包鸿蒙APP全流程】如何配置并添加UniApp API所需的鸿蒙系统权限
华为·uni-app·harmonyos
AAA修煤气灶刘哥10 小时前
物联网-智能设备数据交互核心技术解析
物联网·华为
前端世界10 小时前
HarmonyOS 实战:6 种实现实时数据更新的方案全解析(含完整 Demo)
华为·harmonyos
凯子坚持 c11 小时前
Redis 数据类型:List 列表的深度解析与应用
数据库·redis·list
万少21 小时前
可可图片编辑 HarmonyOS 上架应用分享
前端·harmonyos