本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

HarmonyOS中的List组件是展示结构化、可滚动数据的重要容器,广泛应用于商品列表、联系人、消息记录等场景。本文将全面介绍List组件的使用,包括基础创建、常用API、布局控制、数据绑定、性能优化等核心内容。

一、List组件基础与创建

1. List组件基本概念

List是HarmonyOS中用于显示同类数据集合的滚动容器,具有以下特点:

  • 自动提供滚动功能,适合呈现大量数据
  • 支持垂直和水平两种滚动方向
  • 支持条件渲染、循环渲染和懒加载等优化手段
  • 每个列表项(ListItem)只能包含一个根组件 

2. 基础List创建示例

// 最简单的静态列表创建
@Entry
@Component
struct BasicList {
  build() {
    List() {
      ListItem() {
        Text("列表项1").fontSize(20)
      }
      ListItem() {
        Text("列表项2").fontSize(20)
      }
      ListItem() {
        Text("列表项3").fontSize(20)
      }
    }
    .width('100%')
    .height('100%')
  }
}

3. 动态数据绑定

实际开发中,我们通常使用ForEach动态绑定数据:

class Item {
  key: string;
  name: string;
  icon: Resource;

  constructor(name: string, icon: Resource) {
    this.key = util.generateRandomUUID(true); // 生成唯一key
    this.name = name;
    this.icon = icon;
  }
}

@Entry
@Component
struct DynamicList {
  private items = [
    new Item('商品1', $r("app.media.icon1")),
    new Item('商品2', $r("app.media.icon2")),
    new Item('商品3', $r("app.media.icon3"))
  ]

  build() {
    List() {
      ForEach(this.items, (item: Item) => {
        ListItem() {
          Row() {
            Image(item.icon)
              .width(40)
              .height(40)
              .margin(10)
            Text(item.name).fontSize(20)
          }
          .width('100%')
        }
      }, item => item.key) // 必须提供key生成函数
    }
    .width('100%')
    .height('100%')
  }
}

关键点说明

  • 必须为ForEach提供key生成函数,用于唯一标识列表项 
  • ListItem内部只能有一个根组件,多个组件需要包裹在Row/Column等容器中 
  • 使用Resource($r)引用应用资源 

二、List布局与样式控制

1. 滚动方向设置

List默认是垂直滚动,可通过listDirection属性修改:

List() {
  // 列表项
}
.listDirection(Axis.Horizontal) // 设置为水平滚动

2. 多列/多行布局

通过lanes属性实现多列(垂直列表)或多行(水平列表)布局:

// 固定列数
List() {
  // 列表项
}
.lanes(2) // 两列布局

// 自适应列宽
List() {
  // 列表项
}
.lanes({ minLength: 200, maxLength: 300 }) // 根据宽度自适应

3. 列表项对齐方式

使用alignListItem控制列表项在交叉轴方向的对齐:

List() {
  // 列表项
}
.alignListItem(ListItemAlign.Center) // 居中对齐

4. 间距与分隔线

// 设置列表项间距
List({ space: 10 }) { // 主轴方向间距10vp
  // 列表项
}

// 添加分隔线
List() {
  // 列表项
}
.divider({
  strokeWidth: 2,    // 线宽
  color: Color.Red,  // 颜色
  startMargin: 20,   // 起始边距
  endMargin: 20      // 结束边距
})

5. 内容边距控制

List() {
  // 列表项
}
.contentStartOffset(50) // 顶部内容边距
.contentEndOffset(50)   // 底部内容边距

三、List常用API与高级功能

1. 滚动控制API

List({ initialIndex: 3 }) { // 初始定位到第4个项
  // 列表项
}
.onScrollIndex((start: number, end: number, center: number) => {
  // 滚动位置变化回调
  console.log(`可见项: ${start}到${end}, 中心项: ${center}`);
})
.chainAnimation(true) // 启用链式联动效果

2. 性能优化API

List() {
  // 列表项
}
.cachedCount(5) // 预加载项数
.edgeEffect(EdgeEffect.Spring) // 边缘弹性效果

3. 列表项大小控制

当列表项大小不一致时,需要额外指定:

// 创建大小控制器
childrenMainSize: ChildrenMainSize = new ChildrenMainSize(100)

aboutToAppear() {
  // 设置特定位置项的大小
  this.childrenMainSize.splice(3, 4, [200, 200, 200, 200])
  this.childrenMainSize.update(9, 200)
}

build() {
  List() {
    // 列表项
  }
  .childrenMainSize(this.childrenMainSize) // 应用大小控制
}

4. 复合列表项(ComposeListItem)

HarmonyOS提供了内置的复合列表项组件:

List({ space: 10 }) {
  ComposeListItem({
    contentItem: {
      iconStyle: IconType.HEAD_SCULPTURE,
      icon: $r('app.media.app_icon'),
      primaryText: '主标题',
      secondaryText: '副标题',
      description: '描述文本'
    },
    operateItem: {
      switch: { isCheck: true, onChange: (value) => {} }
    }
  })
  // 更多复合项
}

 5. 嵌套水平滚动列表

        在垂直列表中嵌套水平滚动的子列表,实现类似电商分类页面的效果:

@Entry
@Component
struct NestedList {
  private horizontalItems = [
    { name: '推荐', id: '1' },
    { name: '热门', id: '2' }
  ]

  build() {
    List() {
      ForEach(this.horizontalItems, (item) => {
        ListItem() {
          List({ scroller: new Scroller(), listDirection: Axis.Horizontal }) {
            ForEach([1, 2, 3, 4], (subItem) => {
              ListItem() {
                Text(`子项${subItem}`)
                  .padding(10)
                  .backgroundColor('#f0f0f0')
              }
            })
          }
          .height(100)
          .divider({ strokeWidth: 0 }) // 隐藏分割线
        }
      })
    }
    .nestedScroll({
      scrollForward: NestedScrollMode.PARENT_FIRST, // 父列表优先滚动
      scrollBackward: NestedScrollMode.SELF_FIRST   // 子列表优先回弹
    })
  }
}

关键点

  • 通过nestedScroll配置父子列表的滚动优先级 
  • 水平列表需设置listDirection: Axis.Horizontal 

四、List数据操作与交互

1. 商品列表示例

class Product {
  name: string
  image: Resource
  price: number
  discount: number

  constructor(name: string, image: Resource, price: number, discount = 0) {
    this.name = name
    this.image = image
    this.price = price
    this.discount = discount
  }
}

@Entry
@Component
struct ProductList {
  private products = [
    new Product('Mate60', $r('app.media.a'), 6999, 500),
    new Product('小米', $r('app.media.b'), 4999),
    new Product('OPPO', $r('app.media.c'), 2000)
  ]

  build() {
    List({space: 8}) {
      ForEach(this.products, (item: Product) => {
        ListItem() {
          Row() {
            Image(item.image).width(100).height(100)
            Column({space: 4}) {
              if (item.discount) {
                Text(item.name).fontSize(20).fontWeight(FontWeight.Bold)
                Text(`原价¥${item.price}`)
                  .fontSize(14)
                  .fontColor('#ccc')
                  .decoration({type: TextDecorationType.LineThrough})
                Text(`折扣价¥${item.price - item.discount}`)
                  .fontSize(20)
                  .fontColor('#f36')
              } else {
                Text(item.name).fontSize(20).fontWeight(FontWeight.Bold)
                Text(`¥${item.price}`).fontSize(18).fontColor('#f36')
              }
            }
            .alignItems(HorizontalAlign.Start)
          }
          .width('100%')
          .backgroundColor('#FFF')
          .borderRadius(20)
          .height(120)
          .padding(10)
          .onClick(() => {
            // 点击事件处理
          })
        }
      })
    }
    .width('100%')
    .height('100%')
  }
}

关键特性

  • 支持条件渲染(if/else)显示不同价格信息 
  • 丰富的样式控制(圆角、背景色、内边距等) 
  • 点击事件处理 

2. 分组列表

使用ListItemGroup实现分组:

class Group {
  title: string
  items: Item[]

  constructor(title: string, items: Item[]) {
    this.title = title
    this.items = items
  }
}

@Entry
@Component
struct GroupList {
  private groups = [
    new Group('A组', [new Item('A1', $r('app.media.a1')), ...]),
    new Group('B组', [new Item('B1', $r('app.media.b1')), ...])
  ]

  build() {
    List() {
      ForEach(this.groups, (group: Group) => {
        ListItemGroup() {
          // 组标题
          ListItem() {
            Text(group.title).fontSize(24).fontWeight(FontWeight.Bold)
          }
          
          // 组内项
          ForEach(group.items, (item: Item) => {
            ListItem() {
              // 项内容
            }
          })
        }
      })
    }
  }
}

3侧滑操作(SwipeAction)

        为列表项添加左滑/右滑操作菜单(如删除、收藏):

@Builder
swipeEndBuilder() {
  Button('删除')
    .width(80)
    .height('100%')
    .backgroundColor(Color.Red)
    .onClick(() => { /* 删除逻辑 */ })
}

List() {
  ForEach(this.items, (item) => {
    ListItem() {
      Text(item.name)
    }
    .swipeAction({ end: this.swipeEndBuilder }) // 右滑触发
  })
}

注意

  • swipeAction的Builder中只能包含单个组件 
  • 可通过edgeEffect配置滑动阻尼效果 

4. 拖拽排序 启用列表项拖拽重新排序(需API 7+): 

List() {
  ForEach(this.items, (item) => {
    ListItem() {
      Text(item.name)
    }
    .editable(true) // 启用编辑模式
  })
}
.editMode(true) // 开启列表编辑
.onItemMove((from, to) => { /* 更新数据顺序 */ })

五、总结

1. 性能优化策略

  1. 合理使用key:ForEach必须提供稳定唯一的key,避免使用索引作为key

  2. 控制渲染范围

List() {
  // ...
}
.cachedCount(5) // 预渲染项数

      3. 避免复杂计算:在build函数中避免复杂计算,提前处理数据

      4.使用懒加载:对于复杂列表项,使用LazyForEach替代ForEach 

2. 常见问题解决

  1. 内存泄漏检测

    • 使用DevEco Studio的内存分析工具
    • 检查事件监听器的注销
  2. 列表滚动卡顿

    • 优化列表项布局复杂度
    • 减少不必要的透明度动画
    • 使用willChange提示浏览器优化
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐