HarmonyOS 小游戏《对战五子棋》开发第34篇 - ArkTS中复用UI的方法

把重复的UI代码提取成方法------@Builder是ArkUI的"组件函数"

什么是@Builder

@Builder是ArkTS的装饰器,用于定义可复用的UI构建方法。它类似于"轻量级组件"------不需要声明struct,但可以包含完整的UI代码。

本项目的@Builder使用

AIBattlePage使用了4个@Builder方法:

typescript 复制代码
@Builder
levelSelectView() { /* 关卡选择视图 */ }

@Builder
levelCard(item: LevelConfig) { /* 关卡卡片 */ }

@Builder
gameView() { /* 游戏对战视图 */ }

@Builder
resultDialog() { /* 结果弹窗 */ }

@Builder的调用

typescript 复制代码
build() {
  Stack() {
    Column() {
      // 导航栏...
      if (this.inGame) {
        this.gameView()       // 调用@Builder方法
      } else {
        this.levelSelectView() // 调用@Builder方法
      }
    }

    if (this.inGame && this.showResultDialog) {
      this.resultDialog()      // 调用@Builder方法
    }
  }
}

@Builder方法可以用this.xxx()在build()中调用,就像普通方法一样。

@Builder vs 自定义组件

特性 @Builder @Component struct
声明方式 方法 struct
参数传递 方法参数 @Prop/@Link
状态管理 共享宿主组件状态 独立状态
复用性 仅限当前组件 跨文件复用
适合场景 组件内UI拆分 独立可复用组件

为什么AIBattlePage用@Builder

AIBattlePage有两个主要视图(选关、游戏)和一个弹窗,如果全部写在build()中会非常冗长。用@Builder拆分后:

typescript 复制代码
build() {
  Stack() {
    Column() {
      // 导航栏(共用)
      Row() { ... }
      
      // 根据状态选择视图
      if (this.inGame) {
        this.gameView()       // 100+行UI代码被封装
      } else {
        this.levelSelectView() // 50+行UI代码被封装
      }
    }
    
    if (this.inGame && this.showResultDialog) {
      this.resultDialog()      // 80+行UI代码被封装
    }
  }
}

build()方法变得简洁清晰。

@Builder方法内部访问状态

typescript 复制代码
@Builder
gameView() {
  Column() {
    // 直接访问宿主组件的@State
    Text(this.getStatusText())
    
    if (this.aiThinking) {
      LoadingProgress()
    }
    
    ChessBoardView({
      boardData: this.boardData,
      onCellClick: (row: number, col: number) => {
        this.onCellClick(row, col);
      }
    })
  }
}

@Builder方法可以直接访问宿主组件的所有成员变量和方法------不需要参数传递。

@Builder带参数

typescript 复制代码
@Builder
levelCard(item: LevelConfig) {
  Button() {
    Row({ space: 16 }) {
      Text(item.icon)
        .backgroundColor(item.color)
      
      Column() {
        Text(`第${item.level}关`)
        Text(item.name)
        Text(item.desc)
      }
    }
  }
  .enabled(item.level <= this.unlockedLevel)  // 仍可访问宿主状态
}

参数item是LevelConfig类型,在ForEach中传入:

typescript 复制代码
ForEach(this.levels, (item: LevelConfig) => {
  this.levelCard(item)  // 传参调用
}, (item: LevelConfig) => item.level.toString())

@Builder的嵌套调用

typescript 复制代码
@Builder
levelSelectView() {
  Column({ space: 16 }) {
    Text('选择关卡')
    
    ForEach(this.levels, (item: LevelConfig) => {
      this.levelCard(item)  // @Builder调用@Builder
    }, (item: LevelConfig) => item.level.toString())
  }
}

@Builder方法可以调用其他@Builder方法------形成UI的模块化组合。

ChessBoardView为什么不用@Builder

ChessBoardView是独立组件(@Component export struct),不是@Builder------因为它需要跨文件复用(被TwoPlayerPage和AIBattlePage共用)。

选择原则

  • 仅在当前组件内使用的UI片段 → @Builder
  • 需要跨组件/跨文件复用 → @Component struct

总结

@Builder是ArkUI中组织UI代码的重要工具:

  1. 代码拆分:将冗长的build()方法分解为逻辑单元
  2. 状态共享:直接访问宿主组件的状态
  3. 参数传递:支持方法参数
  4. 嵌套调用:@Builder可以调用@Builder
  5. 适用场景:组件内的UI复用,不需要跨文件

合理使用@Builder可以让复杂的UI代码保持清晰和可维护。

相关推荐
木木子221 小时前
# [特殊字符] 健身模拟器 — 鸿蒙ArkTS完整技术解析
华为·harmonyos
爸爸6191 小时前
鸿蒙实战:@State 本地状态与 UI 刷新
ui·华为·harmonyos·鸿蒙系统
念雨思2 小时前
每日穿搭助手:鸿蒙AI应用开发实战——AI衣橱,每日穿搭不再愁
人工智能·华为·powerpoint·harmonyos·鸿蒙
l134062082352 小时前
鸿蒙实战:从 rawfile 加载 AI 模型资源
人工智能·华为·harmonyos
心中有国也有家2 小时前
AtomGit Flutter 鸿蒙客户端:Flutter 鸿蒙应用的错误处理与优雅降级策略
学习·flutter·华为·harmonyos
xianjixiance_2 小时前
鸿蒙实战:UnclassifiedArchivePage 长按多选与批量归档
华为·harmonyos·鸿蒙系统
不才难以繁此生2 小时前
ArkUI 筛选状态实战:中式美食列表页怎么让关键词、分类和排序不互相打架
harmonyos·arkts·状态管理·arkui·中式美食
●VON3 小时前
HarmonyKit | 鸿蒙开发:hvigor 构建系统命令行与缓存机制详解
缓存·华为·交互·harmonyos·鸿蒙
星释3 小时前
鸿蒙智能体开发实战:35.鸿蒙壁纸大师 - 调用火山引擎模型生成壁纸
算法·华为·ai·harmonyos·鸿蒙·火山引擎