1. 条件渲染 (Conditional Rendering)

条件渲染允许根据状态变量的值,动态决定显示哪些组件。这在处理登录状态、权限控制或不同数据展示场景时非常有用。

1.1 基础语法

在 ArkTS 中,支持标准的 if/else 语句块直接写在 build() 方法内部。

核心规则:

  • ifelse ifelse 必须紧跟在组件容器(如 Column, Row)内部。
  • 每个分支必须返回有效的组件或组件树。
  • 条件判断通常基于组件的状态变量(使用 @State 装饰),但在简单示例中也可以使用普通变量(注意:普通变量变化不会触发 UI 刷新,实际开发中建议使用 @State)。

1.2 示例代码解析

// 定义状态变量,初始值为 3
@State num: number = 3;

@Entry
@Component
struct Index {
  build() {
    Column({ space: 10 }) { // 添加间距使布局更美观
      Text('当前数字:' + this.num)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
      
      // 条件渲染区域
      if (this.num === 1) {
        Text('文本 1')
          .fontSize(30)
          .fontColor(Color.Red)
      } else if (this.num === 2) {
        Text('文本 2')
          .fontSize(30)
          .fontColor(Color.Blue)
      } else {
        // 涵盖 num === 3 及其他所有情况
        Text('文本 else (默认显示)')
          .fontSize(30)
          .fontColor(Color.Green)
      }

      // 模拟交互按钮(仅用于演示状态变化)
      Row({ space: 10 }) {
        Button('设为 1').onClick(() => this.num = 1)
        Button('设为 2').onClick(() => this.num = 2)
        Button('设为 3').onClick(() => this.num = 3)
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

1.3 运行结果说明

  • num1 时:界面显示红色的“文本 1”。
  • num2 时:界面显示蓝色的“文本 2”。
  • num3 (或其他值) 时:界面显示绿色的“文本 else (默认显示)”。
  • 动态性:由于使用了 @State,点击按钮修改变量时,UI 会自动刷新,无需手动操作 DOM。

2. 循环渲染 (Loop Rendering)

循环渲染用于将数组数据映射为一系列相同的组件结构。在 ArkTS 中,主要通过 ForEach 接口实现。

2.1 基础语法

ForEach 需要三个参数(第三个可选):

  1. 数组:要遍历的数据源。
  2. 生成函数(item, index) => { ... },定义如何为每个元素生成组件。
  3. 键生成函数 (可选但推荐):(item) => uniqueKey,用于提高列表更新性能。

重要提示:

  • ForEach 只能作为容器的直接子节点(如 Column, Row, Grid 等)。
  • ForEach 生成的闭包内,不能直接使用外层的 this 上下文中的非静态成员,除非通过箭头函数正确绑定。

2.2 示例代码解析

// 定义数据源
names: string[] = ['大壮', '中壮', '小壮'];

@Entry
@Component
struct Index {
  build() {
    Column({ space: 15 }) {
      Text('家庭成员列表')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 20 })

      // 循环渲染区域
      ForEach(this.names, (item: string, index: number) => {
        Row() {
          Text(`${index + 1}. ${item}`)
            .fontSize(18)
            .fontColor('#333333')
          
          // 添加一个简单的图标或装饰
          Text('👤')
            .fontSize(20)
            .margin({ left: 10 })
        }
        .width('90%')
        .padding(15)
        .backgroundColor('#F5F5F5')
        .borderRadius(10)
        .justifyContent(FlexAlign.SpaceBetween)
      }, (item: string) => item); // 使用名字作为唯一键 (假设名字不重复)

    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Start)
    .padding(20)
  }
}

2.3 运行结果说明

  • 界面会垂直排列三个卡片式的行(Row)。
  • 第一行显示:1. 大壮 👤
  • 第二行显示:2. 中壮 👤
  • 第三行显示:3. 小壮 👤
  • 每个条目都有独立的背景色、圆角和内边距,看起来像一个整齐的列表。

3. 进阶技巧与注意事项

3.1 状态驱动视图

在实际开发中,务必使用 @State@Prop@Link 装饰变量。

  • 错误做法let num: number = 3 (修改后界面不会变)。
  • 正确做法@State num: number = 3 (修改后界面自动重组)。

3.2 ForEach 的键值 (Key)

虽然示例中省略了第三个参数,但在生产环境中,强烈建议提供键值生成函数

  • 作用:帮助框架识别哪些数据项被添加、删除或移动,从而只更新受影响的组件,而不是重绘整个列表。
  • 要求:键值必须是字符串或数字,且在数组中唯一。
// 推荐写法
ForEach(items, (item) => {
  // ...
}, (item) => item.id); // 使用唯一 ID 作为 key

3.3 嵌套使用

条件渲染和循环渲染可以嵌套使用。例如:先判断列表是否为空,如果不为空则循环渲染,否则显示“暂无数据”。

if (this.names.length > 0) {
  ForEach(this.names, (item) => {
    Text(item)
  })
} else {
  Text('暂无数据')
    .fontColor(Color.Gray)
}

总结

特性 条件渲染 (if/else) 循环渲染 (ForEach)
用途 根据布尔值或枚举值显示不同内容 根据数组长度批量生成相同结构的组件
语法位置 直接在 build() 或容器内 必须在容器内作为直接子节点
性能关键 避免复杂的逻辑判断 必须提供唯一的 key 以优化复用
典型场景 登录/未登录视图、空状态页 新闻列表、聊天消息、商品网格
Logo

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

更多推荐