本篇讲解鸿蒙 ArkUI 中的条件渲染机制,分析 if-else 在日记应用中的多种使用场景。

在这里插入图片描述

一、条件渲染概述

在 ArkUI 声明式 UI 中,if-else 用于根据条件决定渲染哪些 UI 组件。当条件变化时,框架会自动更新界面。

二、基本语法

2.1 单条件判断

build() {
  Column() {
    if (this.isLoading) {
      LoadingProgress()
        .width(40)
        .height(40)
    }
  }
}

2.2 if-else 分支

build() {
  Column() {
    if (this.diaries.length === 0) {
      // 空状态
      Text('暂无日记')
        .fontSize(16)
        .fontColor('#999')
    } else {
      // 正常列表
      List() {
        ForEach(this.diaries, (diary: DiaryInfo) => {
          ListItem() {
            this.DiaryCard(diary)
          }
        }, (diary: DiaryInfo) => diary.id)
      }
    }
  }
}

2.3 if-else if-else 多分支

build() {
  Column() {
    if (this.status === 'loading') {
      this.LoadingView()
    } else if (this.status === 'error') {
      this.ErrorView()
    } else if (this.status === 'empty') {
      this.EmptyView()
    } else {
      this.ContentView()
    }
  }
}

三、日记应用中的条件渲染场景

3.1 加载状态切换

if (this.isLoading) {
  Column({ space: 12 }) {
    LoadingProgress()
      .width(40)
      .height(40)
      .color('#007DFF')
    Text('加载中...')
      .fontSize(14)
      .fontColor('#999')
  }
  .width('100%')
  .height('100%')
  .justifyContent(FlexAlign.Center)
} else {
  Scroll() {
    Column() {
      this.DiaryContent()
    }
  }
  .layoutWeight(1)
}

3.2 编辑模式控制

// 编辑模式下显示删除按钮
if (this.isEditMode) {
  Button('删除日记')
    .width('90%')
    .height(48)
    .fontColor('#FF3B30')
    .backgroundColor('#FFFFFF')
    .borderRadius(12)
    .onClick(() => {
      this.showDeleteConfirm()
    })
}

3.3 标签选中状态

ForEach(this.weatherList, (item: WeatherItem) => {
  Text(item.label)
    .fontSize(16)
    .padding(8)
    .borderRadius(20)
    .backgroundColor(
      this.selectedWeather === item.value ? '#007DFF' : '#F5F5F5'
    )
    .fontColor(
      this.selectedWeather === item.value ? '#FFFFFF' : '#333333'
    )
})

3.4 内容截断显示

Text(diary.content)
  .fontSize(14)
  .maxLines(this.isExpanded ? 100 : 2)
  .textOverflow({ overflow: TextOverflow.Ellipsis })

if (diary.content.length > 50) {
  Text(this.isExpanded ? '收起' : '展开')
    .fontSize(14)
    .fontColor('#007DFF')
    .onClick(() => {
      this.isExpanded = !this.isExpanded
    })
}

3.5 日期格式条件显示

if (this.isToday(this.diary.date)) {
  Text('今天')
    .fontSize(12)
    .fontColor('#007DFF')
} else if (this.isYesterday(this.diary.date)) {
  Text('昨天')
    .fontSize(12)
    .fontColor('#666')
} else {
  Text(this.diary.date)
    .fontSize(12)
    .fontColor('#999')
}

四、条件渲染与三目运算符

4.1 三目运算符用于属性值

Text(item.label)
  .backgroundColor(this.isSelected ? '#007DFF' : '#F5F5F5')
  .fontColor(this.isSelected ? '#FFFFFF' : '#333333')
  .fontWeight(this.isSelected ? FontWeight.Bold : FontWeight.Normal)

4.2 三目运算符 vs if-else

// ✅ 使用三目运算符:适合切换属性值
Text(item.label)
  .color(this.isSelected ? '#007DFF' : '#333')

// ✅ 使用 if-else:适合切换整个组件
if (this.isSelected) {
  Image($r('app.media.check'))
    .width(16)
    .height(16)
} else {
  Blank()
}

选择原则:

场景 推荐方式
切换属性值 三目运算符
切换组件结构 if-else
多条件分支 if-else if-else

五、条件渲染的注意事项

5.1 状态变量驱动

条件渲染必须依赖 @State 变量才能自动更新:

@State showDetail: boolean = false

build() {
  Column() {
    Button('切换')
      .onClick(() => {
        this.showDetail = !this.showDetail  // 修改状态触发更新
      })

    if (this.showDetail) {
      Text('详细信息')
    }
  }
}

5.2 避免在 build 中做复杂计算

// ❌ 不推荐:build 中做复杂计算
if (this.diaries.filter(d => d.mood === 'happy').length > 0) {
  Text('有开心的日记')
}

// ✅ 推荐:使用计算属性
@State hasHappyDiary: boolean = false

private checkHappyDiary() {
  this.hasHappyDiary = this.diaries.some(d => d.mood === 'happy')
}

5.3 条件渲染的销毁与重建

// if 条件为 false 时,组件会被销毁
// 当条件变为 true 时,组件会重新创建
if (this.showEditor) {
  TextArea({ text: this.content })
    .onChange((value: string) => {
      this.content = value
    })
}
// 如果 showEditor 从 true → false → true
// TextArea 会被销毁再重建,之前输入的内容会丢失

解决方案: 使用 visibility 属性代替条件渲染:

TextArea({ text: this.content })
  .onChange((value: string) => {
    this.content = value
  })
  .visibility(this.showEditor ? Visibility.Visible : Visibility.Hidden)

六、Visibility 属性

enum Visibility {
  Visible,   // 可见
  Hidden,    // 隐藏,但占位
  None       // 隐藏,不占位
}
Column() {
  Text('标题')
  Text('副标题')
    .visibility(this.showSubtitle ? Visibility.Visible : Visibility.None)
  Text('内容')
}

Visibility vs if-else

特性 Visibility.None if-else
组件销毁 否,保留在内存 是,完全销毁
状态保留 保留 丢失
性能 占用内存 释放内存
适用场景 频繁切换 不常切换

七、条件渲染实战模式

7.1 页面状态机

type PageStatus = 'loading' | 'success' | 'error' | 'empty'

@State status: PageStatus = 'loading'

build() {
  Column() {
    if (this.status === 'loading') {
      this.LoadingView()
    } else if (this.status === 'error') {
      this.ErrorView()
    } else if (this.status === 'empty') {
      this.EmptyView()
    } else {
      this.SuccessView()
    }
  }
}

7.2 权限控制

if (this.userRole === 'admin') {
  Button('管理后台')
    .onClick(() => {
      this.goToAdmin()
    })
}

八、总结

条件渲染的核心要点:

  1. if-else:用于切换组件结构,条件变化时自动更新
  2. 三目运算符:用于切换属性值,代码更简洁
  3. 状态驱动:条件必须依赖 @State 变量
  4. Visibility:需要保留状态时用 visibility 替代 if-else
  5. 避免复杂计算:不在 build 中做复杂逻辑运算
  6. 状态机模式:多状态页面用状态机管理更清晰

条件渲染是声明式 UI 的基础能力,合理使用可以让界面逻辑清晰、性能高效。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐