HarmonyOS鸿蒙Next中使用@State + if/else + visibility实现多状态页面(加载中/成功/空数据/错误)的统一管理

HarmonyOS鸿蒙Next中使用@State + if/else + visibility实现多状态页面(加载中/成功/空数据/错误)的统一管理 我们应该发如何通过使用 [@State](/user/State) + if/else + visibility 来实现多状态页面(加载中 / 成功 / 空数据 / 错误)的统一管理呢?

3 回复

使用场景

在很多业务场景下,我们都需要可能碰到比如商品页无商品、消息页无消息、文章加载失败等各种空或者异常的业务情况 ,但有时候我们开发会将状态各自设定,导致比较分散混乱。

实现思路

采用状态机的模式,我们用一个枚举 + 单一状态变量统一管理所有页面状态。https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/561/716/646/0030086000561716646.20251210094558.18497728134291598936813257286212:50001231000000:2800:DC7BC0C008786A916D6E9A7C189AF55140BB3B45C60CFEB544079D3A8A697C05.gif

enum PageStatus {
  Loading,
  Success,
  Empty,
  Error
}

然后在页面中使用时,只依赖于单一的状态源。以此进行解耦

完整代码

enum PageStatus {
  Loading,
  Success,
  Empty,
  Error
}

@Entry
@Component
struct OrderListPage {
  @State status: PageStatus = PageStatus.Loading;
  @State orders: string[] = [];
  @State errorMessage: string = '';

  // 模拟加载订单数据
  aboutToAppear() {
    this.loadData();
  }

  private async loadData() {
    this.status = PageStatus.Loading;

    try {
      // 模拟网络延迟
      // await new Promise(resolve => setTimeout(resolve, 1500));

      // 模拟不同结果(可注释某行测试不同状态)
      // const mockData = ['订单 #20251201', '订单 #20251202']; // 正常数据
      // const mockData: string[] = []; // 取消注释此行可测试“空数据”
      throw new Error('服务器繁忙'); // 取消注释此行可测试“错误”

      // if (mockData.length === 0) {
      //   this.status = PageStatus.Empty;
      // } else {
      //   this.orders = mockData;
      //   this.status = PageStatus.Success;
      // }
    } catch (e) {
      this.errorMessage = e.message || '加载失败,请重试';
      this.status = PageStatus.Error;
    }
  }

  build() {
    Column({ space: 20 }) {
      Text('我的订单')
        .fontSize(22)
        .fontWeight(FontWeight.Bold)

      // 统一状态渲染
      if (this.status === PageStatus.Loading) {
        Column() {
          Text('加载中...')
            .fontColor('#999')
            .fontSize(14)
        }
        .margin({ top: 100 })
      } else if (this.status === PageStatus.Success) {
        List({ space: 10 }) {
          ForEach(
            this.orders,
            (order: string) => {
              ListItem() {
                Text(order)
                  .padding(15)
                  .width('100%')
                  .borderRadius(8)
                  .backgroundColor('#F8F9FA')
              }
            }
          )
        }
        .width('100%')
        .height('60%')
      } else if (this.status === PageStatus.Empty) {
        Column() {
          Image($r('app.media.startIcon'))
            .width(80)
            .height(80)
            .margin({ bottom: 15 })
            .visibility(Visibility.Visible) // 图标占位(可选)
          Text('暂无订单')
            .fontColor('#999')
            .fontSize(16)
          Button('去逛逛')
            .width(120)
            .height(40)
            .margin({ top: 15 })
            .backgroundColor('#007DFF')
            .onClick(() => {
              // 跳转首页等

            })
        }
        .margin({ top: 100 })
      } else if (this.status === PageStatus.Error) {
        Column() {
          Image($r('app.media.startIcon'))
            .width(80)
            .height(80)
            .margin({ bottom: 15 })
          Text(this.errorMessage)
            .fontColor(Color.Red)
            .fontSize(16)
            .textAlign(TextAlign.Center)
            .width('80%')
          Button('重试')
            .width(120)
            .height(40)
            .margin({ top: 20 })
            .backgroundColor('#007DFF')
            .onClick(() => {
              this.loadData(); // 重新加载
            })
        }
        .margin({ top: 100 })
      }
    }
    .padding(25)
    .width('100%')
    .height('100%')
  }
}

function ProgressIndicator() {
  throw new Error('Function not implemented.');
}

实现效果

通过统一的状态机来显示不 同状态下的场景。

cke_7474.png

cke_5457.png

cke_2943.png

更多关于HarmonyOS鸿蒙Next中使用@State + if/else + visibility实现多状态页面(加载中/成功/空数据/错误)的统一管理的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用@State装饰器管理页面状态,结合if/else条件渲染和visibility属性控制组件显示,实现加载中、成功、空数据和错误状态的统一管理。@State定义状态变量,if/else根据状态值渲染对应组件,visibility控制组件可见性。这种方法简化了多状态页面的代码结构,提升了开发效率。

在HarmonyOS Next中,使用[@State](/user/State)、条件渲染(if/else)和visibility来统一管理多状态页面是一种清晰且高效的做法。以下是实现方案:

1. 定义状态枚举

首先,使用枚举明确定义页面的几种状态:

enum PageState {
  Loading,  // 加载中
  Success,  // 成功(有数据)
  Empty,    // 空数据
  Error     // 错误
}

2. 使用@State管理状态

在组件中,使用[@State](/user/State)装饰器声明一个状态变量来跟踪当前页面状态:

[@State](/user/State) currentState: PageState = PageState.Loading

3. 条件渲染实现状态切换

build()方法中,使用条件渲染(if/else)根据当前状态显示不同的UI:

build() {
  Column() {
    // 加载中状态
    if (this.currentState === PageState.Loading) {
      LoadingComponent()
    }
    
    // 成功状态(显示数据)
    if (this.currentState === PageState.Success) {
      DataContentComponent()
    }
    
    // 空数据状态
    if (this.currentState === PageState.Empty) {
      EmptyStateComponent()
    }
    
    // 错误状态
    if (this.currentState === PageState.Error) {
      ErrorComponent()
    }
  }
}

4. 使用visibility优化渲染

对于某些场景,可以使用visibility属性替代条件渲染,避免组件树频繁重建:

build() {
  Column() {
    // 使用visibility控制显示
    LoadingComponent()
      .visibility(this.currentState === PageState.Loading ? Visibility.Visible : Visibility.None)
    
    DataContentComponent()
      .visibility(this.currentState === PageState.Success ? Visibility.Visible : Visibility.None)
    
    EmptyStateComponent()
      .visibility(this.currentState === PageState.Empty ? Visibility.Visible : Visibility.None)
    
    ErrorComponent()
      .visibility(this.currentState === PageState.Error ? Visibility.Visible : Visibility.None)
  }
}

5. 状态切换示例

在数据加载逻辑中更新状态:

async loadData() {
  this.currentState = PageState.Loading
  
  try {
    const data = await api.fetchData()
    
    if (data.length === 0) {
      this.currentState = PageState.Empty
    } else {
      this.currentState = PageState.Success
      // 更新数据
    }
  } catch (error) {
    this.currentState = PageState.Error
  }
}

选择建议

  • 条件渲染(if/else):适合状态间UI差异大、组件结构不同的场景,不同状态组件完全独立
  • visibility控制:适合状态间UI结构相似、仅内容变化的场景,避免组件重建开销

这种模式将状态管理集中化,使状态切换逻辑清晰,便于维护和扩展。

回到顶部