源码获取

如果你想一边对照文章一边实操,建议直接把示例工程拉到本地。项目 Git 地址:https://gitcode.com/HarmonyOS_Samples/CommonListFlows

很多人写列表页,最开始都会经历一个阶段: 页面能出来,代码也能跑,但越写越像一堵墙。

尤其是列表项。刚开始只有一张图一行字,你会觉得塞在 build() 里也没什么。等它慢慢长出头像、来源、时间、摘要、三张配图、角标、标签,页面代码就会突然变得特别难看。

CustomListItem 这个组件虽然不大,但特别适合拿来说明一件事: 只要列表项已经形成稳定结构,就该尽早把它抽出来。

先别急着看写法,先看它像不像真实内容卡片

A 'before and after' comparison sketch illustratin

这个组件最像哪类东西?

我觉得特别像资讯流、社区流、推荐流里的标准卡片。一个条目里通常会有这些元素:

  • 一个头像或封面图
  • 一块来源信息
  • 一段正文摘要
  • 一排配图

这其实就是你以后最常碰到的列表卡片模型之一。

项目里的 CustomListItem 长什么样

源码本身很直白:

@Component
export struct CustomListItem {
  @State title: string | ResourceStr = ''
  @State imgUrl: string | ResourceStr = ''

  build() {
    Column() {
      Row() {
        Image(this.imgUrl)
          .width(40)
          .height(40)
          .borderRadius(20)

        Column() {
          Text($r('app.string.security'))
          Text('示例时间')
        }
      }

      Text(this.title)
        .margin({ top: 12, bottom: 12 })

      Row() {
        Image(this.imgUrl)
        Image(this.imgUrl)
        Image(this.imgUrl)
      }
    }
    .padding(12)
    .borderRadius(16)
    .backgroundColor(Color.White)
  }
}

A technical blueprint diagram of the 'CustomListIt

这段代码本身不复杂,但拆得很像一张完整卡片:

  • 顶部是来源信息区
  • 中间是摘要区
  • 底部是多图区

当你能从“代码块”开始切换成“卡片结构”去看问题,组件化思路就会自然很多。

为什么这类列表项更适合抽成独立组件

很多新手会问,那为什么不直接写成一个 @Builder

当然也不是不行,但我更推荐这里用独立组件。原因非常现实:

  • 复用更自然
  • 页面主结构会清爽很多
  • 以后加事件、状态、样式变化更方便

简单说,如果只是页面里一小段重复布局,Builder 挺好用;但只要它已经像一张“卡片”,我更建议你把它当组件看。

因为这时候它已经不是一段小 UI,而是一个完整的展示单元了。

ManagerPage 是怎么复用它的

到了 ManagerPage,页面本身不再关心卡片内部怎么排,只关心“我这里要显示几张卡片、每张卡片喂什么数据”:

List({ space: 10, scroller: this.listScroller }) {
  CustomListItem({
    imgUrl: $r('app.media.pic1'),
    title: $r('app.string.manager_content')
  })

  CustomListItem({
    imgUrl: $r('app.media.pic2'),
    title: $r('app.string.manager_content')
  })
}

你会发现,页面代码一下子轻了很多。

这就是组件化最直接的好处。主页面负责摆结构,卡片组件负责管自己长什么样。职责一分开,代码读起来就舒服得多。

这种卡片最适合怎么拆

如果你以后自己做类似卡片,我很建议你先按区域拆,而不是按控件拆。

比如 CustomListItem 就很适合先想成这三块:

  • 头部信息区
  • 正文摘要区
  • 附件图片区

这个思路特别有用。

因为当你按区域拆时,布局会更像真实产品;如果你一上来只盯着“这里一个 Text,那里一个 Image”,最后代码往往会很碎,结构感也很差。

为什么说它特别适合小白练手

别看这只是个小组件,它其实把很多常见动作都顺手练到了:

  • 圆角头像
  • 文本分层
  • 上下间距控制
  • 横向排布
  • 多图均分
  • 白底卡片容器

这些能力单独拿出来都不难,但能不能把它们自然地组合成一张卡片,这才是页面感的来源。

这里有个细节,我建议你早点建立意识

项目里这样定义属性:

A warm-toned illustration of a developer's workspa

@State title: string | ResourceStr = ''
@State imgUrl: string | ResourceStr = ''

从示例工程角度看,这样写没问题,代码也够短。

但如果你以后做更正式的组件,我会建议你早点分清一件事: 外部传进来的展示数据,和组件内部自己维护的状态,不是一回事。

说白了,卡片标题、图片这类内容,本质上更像“输入”,不是卡片自己临时产生的“内部状态”。现在你先有这个概念,后面进阶会轻松很多。

如果你想把这个组件改成自己的风格,先改这三刀

别一上来就想着做万能组件,先把当前页面的气质改顺。

我建议你优先改这三处:

  • 把顶部来源名换成你自己的演示栏目
  • 把时间换成“刚刚”“10 分钟前”这种更真实的展示文案
  • 把底部三图改成一张大图或两张并排图

这三刀下去,你会立刻感受到: 结构不变,页面观感却能差很多。

这类组件最常见的坏习惯,其实非常固定

列表项都重复三遍了,还不拆

短期看复制粘贴很快,后面一改样式就要全项目手抄,特别痛苦。

组件拆出来了,却把复杂业务判断也塞进去

这样会让卡片越来越重。展示组件最好先聚焦展示,复杂逻辑能留给上层就留给上层。

一上来就想做“宇宙级通用组件”

这几乎是新手通病。结果往往是参数越来越多,谁都不爱改。先把当前页面服务好,比幻想一个万能组件靠谱得多。

这篇还顺手给了一个很实在的脱敏思路

项目原始资源里有固定文案和时间示例。写教程时,我前面已经把它们改成更中性的表达,这其实就是一个很实战的习惯。

技术教程里,最好让读者知道这些只是演示数据,不是你在灌输某个固定业务场景。这样后面别人拿去改成校园资讯、社区帖子、课程推荐,也会更顺。

最后一句

列表页真正拉开差距的,不是你会不会写 List,而是你有没有在重复结构出现的时候,及时把它从主页面里拎出来。

CustomListItem 这个例子不算大,但它特别适合帮你养成一个值钱的习惯: 复杂列表项别一股脑塞进 build(),早点组件化,后面真的会轻松很多。

Logo

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

更多推荐