ArkUI 自定义组件:复制三遍的 UI 就该抽出来

举报
蓝瘦的蜕变 发表于 2026/11/15 23:39:50 2026/11/15
【摘要】 今天我们把重复卡片抽成一个自定义组件。 写页面时最容易偷懒的地方,就是同一种卡片复制几遍,然后只改里面的文案。刚开始这样写没问题,但复制到第三遍,你大概率就该停一下:结构是不是可以收起来了? 这个 Demo 只做一件事:父组件准备内容,子组件 ReusedFeatureCard 负责统一卡片结构。 这个 Demo 看什

ArkUI 自定义组件:复制三遍的 UI 就该抽出来

今天我们把重复卡片抽成一个自定义组件。

写页面时最容易偷懒的地方,就是同一种卡片复制几遍,然后只改里面的文案。刚开始这样写没问题,但复制到第三遍,你大概率就该停一下:结构是不是可以收起来了?

这个 Demo 只做一件事:父组件准备内容,子组件 ReusedFeatureCard 负责统一卡片结构。

这个 Demo 看什么

页面里有一个 CustomFeatureItem,用来承载标题、说明、标签和颜色。父组件只维护这组数据。

真正的 UI 样式放在 ReusedFeatureCard 里:

  • 左侧色条统一。
  • 标题和标签统一。
  • 说明文字统一。
  • 圆角、边框、留白统一。

这样做的好处很直接:以后卡片间距想改,只改子组件;父组件不用关心每张卡片怎么排版。

这里我们故意不讲状态同步。自定义组件第一步先别做复杂,能把重复 UI 抽出来,就已经解决了很真实的问题。

你自己项目里有没有那种复制了好几遍的卡片、列表项或者标题区?一般先从这种地方抽组件,收益最明显。

完整代码

class CustomFeatureItem {
  title: string;
  summary: string;
  labelText: string;
  accentColor: string;

  constructor(title: string, summary: string, labelText: string, accentColor: string) {
    this.title = title;
    this.summary = summary;
    this.labelText = labelText;
    this.accentColor = accentColor;
  }
}

@Component
struct ReusedFeatureCard {
  title: string = '';
  summary: string = '';
  labelText: string = '';
  accentColor: string = '#2563EB';

  build() {
    Row({ space: 14 }) {
      Text('')
        .width(6)
        .height(74)
        .borderRadius(3)
        .backgroundColor(this.accentColor)

      Column({ space: 8 }) {
        Row({ space: 8 }) {
          Text(this.title)
            .fontSize(18)
            .fontWeight(700)
            .fontColor('#111827')
            .layoutWeight(1)
          Text(this.labelText)
            .fontSize(12)
            .fontColor(this.accentColor)
            .padding({ left: 10, right: 10, top: 4, bottom: 4 })
            .borderRadius(12)
            .backgroundColor('#F8FAFC')
        }
        .width('100%')

        Text(this.summary)
          .fontSize(14)
          .fontColor('#4B5563')
          .lineHeight(21)
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .padding(16)
    .borderRadius(16)
    .backgroundColor('#FFFFFF')
    .border({ width: 1, color: '#E5E7EB' })
  }
}

@Entry
@Component
struct ArkUICustomComponentDemo {
  private features: CustomFeatureItem[] = [
    new CustomFeatureItem('统一标题区', '同一种卡片结构,不要在页面里复制三遍标题、说明和标签样式。', '结构', '#2563EB'),
    new CustomFeatureItem('统一视觉边界', '圆角、边框、留白放在子组件里,父组件只关心展示什么。', '样式', '#0F766E'),
    new CustomFeatureItem('统一内容入口', '父组件传入标题、说明、颜色和标签,子组件负责把它摆整齐。', '传参', '#B45309')
  ];

  @Builder
  HeaderBlock() {
    Column({ space: 8 }) {
      Text('ArkUI 自定义组件')
        .fontSize(28)
        .fontWeight(700)
        .fontColor('#111827')
      Text('复制三遍的 UI 就该抽出来')
        .fontSize(16)
        .fontColor('#4B5563')
      Text('这个页面只看最普通的自定义组件:父组件传内容,子组件统一结构。先别急着做组件库,能把重复卡片抽出来就已经很值。')
        .fontSize(14)
        .fontColor('#6B7280')
        .lineHeight(22)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  build() {
    Scroll() {
      Column({ space: 20 }) {
        this.HeaderBlock()

        Column({ space: 12 }) {
          ForEach(this.features, (item: CustomFeatureItem) => {
            ReusedFeatureCard({
              title: item.title,
              summary: item.summary,
              labelText: item.labelText,
              accentColor: item.accentColor
            })
          }, (item: CustomFeatureItem) => item.title)
        }
        .width('100%')

        Text('这里没有讲状态同步,因为它不是本篇重点。我们先把“重复 UI 抽成组件”这件小事做好,后面再谈组件之间怎么传变化。')
          .width('100%')
          .padding(16)
          .borderRadius(16)
          .backgroundColor('#F8FAFC')
          .fontSize(14)
          .fontColor('#4B5563')
          .lineHeight(22)
      }
      .width('100%')
      .padding(24)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFFFFF')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。