HarmonyOS

发布于:2025-04-20 ⋅ 阅读:(14) ⋅ 点赞:(0)

1. 组件基础

开发环境

1. 起步-鸿蒙简介

介绍:

HarmonyOS是新一代的智能终端操作系统,为不同设备的智能化、互联与协同提供了统一的语言。带来简洁,流畅,连续,安全可靠的全场景交互体验。

历程:

时间 事件
2019 HarmonyOS 1.0,华为在东莞举行华为开发者大会,正式发布操作系统鸿蒙 OS,主要用于物联网
2020 HarmonyOS 2.0,基于开源项目 OpenHarmony 开发的面向多种全场景智能设备的商用版本
2021 HarmonyOS 3.0,先后优化游戏流畅度、地图三维体验、系统安全,另外系统的稳定性也得到了增强
2023.2 HarmonyOS 3.1,系统纯净能力进一步提升,对后台弹窗、 隐藏应用、后台跳转等情况
2023.7 华为 Mate 50 系列手机获推 HarmonyOS 4.0
2024 HarmonyOS Next 即将发布,将不在兼容安卓应用

2. 起步-DevEco Studio

在这里插入图片描述

安装 DevEco Studio 编辑器

3. 起步-HelloWorld

创建一个空项目

  • 新建-新建项目
    在这里插入图片描述

  • 选择项目模板在这里插入图片描述

  • 填写项目信息
    在这里插入图片描述

  • Finish
    在这里插入图片描述

4. 起步-效果预览

  • Previewer 预览

    场景:静态页面(没有组件间数据通信、不涉及到网络请求)
    条件:有 @Entry 或 @Preview 装饰器页面

  • Local Emulator 本地模拟器

    场景:动态页面(几乎全场景,一些无法模拟的硬件功能)

  • Remote Emulator 远程模拟器
  • Remote Device 远程真机
  • Local Device 本地真机

5. 起步-工程结构

我们在哪里写代码?

目录 作用
entry 是一个 Module 应用包
entryability 是一个 UIAbility 包含用户界面的应用组件
pages 页面
components 组件

组件基础

1. 组件-什么是ArkTS

ArkTS是HarmonyOS优选的主力应用开发语言。
ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。

2. 基础-组件结构

ArkTS通过装饰器 @Component 和 @Entry 装饰 struct 关键字声明的数据结构,构成一个自定义组件。
自定义组件中提供了一个 build 函数,开发者需在该函数内以链式调用的方式进行基本的 UI 描述,UI 描述的方法请参考 UI 描述规范。

页面组件

@Entry
@Component
struct Index {
  // 工程默认显示 `Index` 页面组件
  // build 是声明UI的位置
  build() {
    Text('页面组件')
  }
}

自定义组件

// 定义 `Footer` 组件
@Component
struct Footer {
  build() {
    Text('自定义组件')
  }
}

@Entry
@Component
struct Index {
  build() {
    Column(){
      // 使用 `Footer` 组件
      Footer()
    }
  }
}

注意: 为了更好维护,自定义组件通常会新建一个文件 Footer.ets,通过模块化语法导出导入(默认|按需)使用。

3. 基础-系统组件(ArkUI)

常用系统组件 Text Column Row Button TextInput 更多组件

  • Text 文本组件
  • Column 列组件,纵向排列,Flex布局主轴是Y
  • Row 行组件,横向向排列,Flex布局主轴是X
  • Button 按钮组件
  • InputText 输入框组件

实现一个简易登录界面:

@Entry
@Component
struct Index {
  @State
  phone:string = '18852638009'
  yzm:string= 'ws34'
  build() {
    Column(){
      // 手机号
      Row(){
        Text('手机号:')
        TextInput({text:this.phone, placeholder: '请输入手机号'})
          .placeholderColor('red')
      }
      // 验证码
      Row(){
        Text('验证码:')
        TextInput({text:this.yzm, placeholder: '请输入验证码'})
          .maxLength(4)
      }
      // 验证码
      Row(){
        Text('忘记密码')
          .fontColor('#FF2B71F3')
      }
    // 登录,注册按钮
      Row(){
        Button('注册')
          .backgroundColor('#c3c4c5')
          .onClick(()=>{
            console.log('注册')
          })
        Button('登录')
          .onClick(()=>{
            console.log('登录')
          })
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#ffececec')
  }

}

注意: ArkUI 组件一般都是 Flex 模式,大部分布局可以由行和列组成。

4. 基础-组件状态

如何使用 @State 定义一个状态变量?

组件变量,不具备驱动UI更新能力。

@Entry
@Component
struct Index {
  count = 100

  build() {
    Text(this.count.toString())
      .onClick(() => this.count++)
  }
}

状态变量,指驱动UI更新的数据,加上 @State 装饰器即可,注意:加上类型和初始值。

@Entry
@Component
struct Index {

  @State
  count: number = 100
//状态变量不可设置的类型有:any undefined null 与复杂类型的联合类型
  build() {
    Text(this.count.toString())
      .onClick(() => this.count++)
  }
}

5. 练习案例

实现登录表单数据收集、重置、模拟提交。

import promptAction from '@ohos.promptAction'
@Entry
@Component
struct Index {

  @State
  mobile: string = ''
  @State
  code: string = ''

  build() {
    Column(){
      Row(){
        Text('手机号')
        TextInput({ text: this.mobile })
          .onChange((value)=>this.mobile = value)
      }
      Row(){
        Text('验证码')
        TextInput({ text: this.code })
          .onChange((value)=>this.code = value)
      }
      Row(){
        Button('重置')
          .backgroundColor('#ccc')
          .onClick(()=>{
            this.mobile = ''
            this.code = ''
          })
        Button('登录')
          .onClick(()=>{
            if (this.mobile && this.code) {
              promptAction.showToast({ message: `${this.mobile} 登录成功` })
            } else {
              promptAction.showToast({ message: `请输入手机号或验证码` })
            }
          })
      }
    }
  }
}

在这里插入图片描述

样式布局

1. 基础布局

用途:用于实现垂直或水平排列的简单布局,适用于需要线性排列的场景(如导航栏、列表等)。

  • Column:纵向排列(从上到下)。
  • Row:横向排列(从左到右)。

关键属性

属性 描述
space 子组件之间的间距(单位:px)。
direction (Row/Column的父容器)设置主轴方向(Row为水平,Column为垂直)。
width/height 容器的尺寸(支持百分比或固定值)。
  • 纵向布局(Column)案例:
    在这里插入图片描述

@Entry
@Component
struct Test{
  build() {
    Column(){
      // 纵向布局(Column)
      Column({ space: 20 }) {
        Row().width('100%').height(200).backgroundColor(Color.Pink)
        Row().width('100%').height(200).backgroundColor(Color.Blue)
        Row().width('100%').height(200).backgroundColor(Color.Yellow)
      }.width('100%').height('100%')

      // // 横向布局(Row)
      // Row({ space: 20 }) {
      //   Column().width(100).height('100%').backgroundColor(Color.Pink)
      //   Column().width(100).height('100%').backgroundColor(Color.Blue)
      //   Column().width(100).height('100%').backgroundColor(Color.Yellow)
      // }.width('100%').height('100%')
    }
    .width('100%')
    .height('100%')

  }
}
  • 横向布局(Row)案例:

在这里插入图片描述


@Entry
@Component
struct Test{
  build() {
    Column(){
      // 横向布局(Row)
      Row({ space: 20 }) {
        Column().width(100).height('100%').backgroundColor(Color.Pink)
        Column().width(100).height('100%').backgroundColor(Color.Blue)
        Column().width(100).height('100%').backgroundColor(Color.Yellow)
      }.width('100%').height('100%')
    }
    .width('100%')
    .height('100%')
  }
}

Row 和Column的布局方式成为线性布局- 不是横向排列就是纵向排列
● 线性布局中永远不会产生换行
● 均不支持出现滚动条
● 横向排列的垂直居中,总行排列的水平居中
● 主轴-排列方向的轴
● 侧轴-排列方向垂直的轴

2. 堆叠布局(Stack)

用途:用于实现层叠效果,后添加的组件会覆盖前一个组件,适合需要重叠的复杂布局(如弹窗、图层叠加)。

关键属性

属性 描述
alignContent 设置子组件的对齐方式(如 Alignment.TopEnd)。
width/height 容器的尺寸(必须显式设置)。

Stack的参数 可以设置子组件的排列方式alignContent

  • Top(顶部)

  • TopStart(左上角)

  • TopEnd(右上角)

  • Start(左侧)

  • End(右侧)

  • Center(中间)

  • Bottom(底部)

  • BottomStart(左下角)

  • BottomEnd(右下角)

  • 案例:
    在这里插入图片描述

@Entry
@Component
struct Test {
  build() {
    Row() {
      Stack() {
        Text('抖音')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .fontColor('#ff2d83b3')
          .translate({
            x:-2,
            y:2
          })
          .zIndex(1)
        Text('抖音')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .fontColor('#ffe31fa9')
          .translate({
            x:2,
            y:-2
          })
          .zIndex(2)

        Text('抖音')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .fontColor('#ff030000')
          .translate({
            x:0,
            y:0
          })
          .zIndex(3)

      }
      .width('100%')
    }
    .height('100%')
  }
}

3. 弹性布局

用途:通过灵活的主轴和交叉轴对齐,适配不同屏幕尺寸和动态内容(如自适应导航栏、卡片布局)。

关键属性

属性 描述
direction 主轴方向(FlexDirection.Row 或 FlexDirection.Column)。
justifyContent 主轴对齐方式(如 FlexAlign.SpaceBetween)。
alignItems 交叉轴对齐方式(如 ItemAlign.Center)。
flexGrow 子组件的拉伸权重(值越大,占据空间越多)。

案例:
在这里插入图片描述

@Entry
@Component
struct Test {
  build() {
    Flex({ direction: FlexDirection.Column }){

        Column(){
          Text('一行两列')
          Flex(){
            Text('数据1')
              .width('50%')
              .backgroundColor(Color.Green)
              .textAlign(TextAlign.Center)
            Text('数据2')
              .width('50%')
              .backgroundColor(Color.Orange)
              .textAlign(TextAlign.Center)
          }
      }
        Column(){
          Text('一行一列')
          Flex({direction:FlexDirection.Column}){
            Text('数据1')
              .width('100%')
              .backgroundColor(Color.Green)
              .textAlign(TextAlign.Center)
            Text('数据2')
              .width('100%')
              .backgroundColor(Color.Orange)
              .textAlign(TextAlign.Center)
          }

      }.margin({
          top:'10'
        })
    }
      .width('100%')
      .height('100%')
      .backgroundColor(Color.Pink)
  }
}

4. 网格布局

用途:通过行列划分实现复杂布局(如商品列表、仪表盘),支持响应式设计。

关键属性

属性 描述
columnsTemplate 定义列模板(如 1fr 1fr 表示两列等分)。
rowsTemplate 定义行模板(如 auto 100px)。
span 子组件跨的列数或行数(如 GridColSpan(2))。
gutte 列与列之间的间距(如 { x: 8, y: 12 })。

案例:
在这里插入图片描述

@Entry
@Component
struct Test {
  build() {
    Grid() {
      GridItemCases()
      GridItemCases()
      GridItemCases()
      GridItemCases()
      GridItemCases()
      GridItemCases()
    }
    .width("100%")
    .height("100%")
    .columnsTemplate("1fr 1fr 1fr")
    .columnsGap(10)
    .rowsGap(10)
    .padding(10)

  }
}

@Component
struct GridItemCases {
  build() {
    GridItem() {
      Row() {
        Column() {
          Text("grid布局")
        }
        .width('100%')
      }
      .height(200)
      .borderRadius(4)
      .backgroundColor(Color.Pink)
    }

  }
}

5. 相对布局(RelativeContainer)

用途:通过锚点规则实现精准的相对定位,适合需要动态调整位置的场景(如动态弹窗、自定义表单)。

关键属性

属性 描述
alignRules 定义子组件的锚点对齐规则(需配合 id 使用)。
id 子组件的唯一标识(必须设置)。
container 参与相对布局的容器内组件若被设备锚点,需要设置id,否则不显示

案例:
在这里插入图片描述

@Entry
@Component
struct Test {
  build() {
    RelativeContainer() {
      RelativeContainer() {
        Row(){}
        .width('33%')
        .aspectRatio(1)
        .alignRules({
          top: { anchor: '__container__', align: VerticalAlign.Top },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
        .backgroundColor(Color.Red)
        Row(){}
        .width('33%')
        .aspectRatio(1)
        .alignRules({
          bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
        .backgroundColor(Color.Yellow)
        Row(){}
        .width('33%')
        .aspectRatio(1)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          left: { anchor: '__container__', align: HorizontalAlign.Start }
        })
        .backgroundColor(Color.Blue)
        .zIndex(2)
        Row(){}
        .width('33%')
        .aspectRatio(1)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          right: { anchor: '__container__', align: HorizontalAlign.End }
        })
        .backgroundColor(Color.Green)
      }
      .width('60%')
      .aspectRatio(1)
      .backgroundColor(Color.Pink)
      .alignRules({
        center: { anchor: '__container__', align: VerticalAlign.Center },
        middle: { anchor: '__container__', align: HorizontalAlign.Center }
      })
    }
    .height('100%')
    .width('100%')
    .id('firstContainer')
    .backgroundColor(Color.Gray)
  }
}

6. 滚动条说明(Scroll)

用途:实现可滚动区域,适用于内容超出容器大小的场景(如长列表、图文详情页)。

关键属性

属性 描述
scrollDirection 滚动方向(ScrollDirection.Vertical 或 ScrollDirection.Horizontal)。
bounce 是否允许弹性回弹(默认 true)。
overscroll 是否允许滚动超出边界时的阴影效果(默认 true)。

样式处理

1. 样式-语法(链式&枚举)

ArkTS以声明方式组合和扩展组件来描述应用程序的UI;
同时还提供了基本的属性、事件和子组件配置方法,帮助开发者实现应用交互逻辑。
样式相关属性通过链式函数的方式进行设置
如果类型是枚举的,通过枚举传入对应的值

样式属性

  • 属性方法以 . 链式调用的方式配置系统组件的样式和其他属性,建议每个属性方法单独写一行。
@Entry
@Component
struct Index {
  build() {
    Text('演示')
      .backgroundColor('red')
      .fontSize(50)
      .width('100%')
      .height(100)
  }
}

枚举值

  • 对于系统组件,ArkUI还为其属性预定义了一些枚举类型。文档链接
@Entry
@Component
struct Index {
  build() {
    Text('演示')
      .fontSize(50)
      .width('100%')
      .height(100)
      .backgroundColor(Color.Blue)
      .textAlign(TextAlign.Center)
      .fontColor(Color.White)
  }
}

2. 样式-单位vp和适配

vp (virtual pixel)是什么?

  • 屏幕密度相关像素,根据屏幕像素密度转换为屏幕物理像素,当数值不带单位时,默认单位 vp;
  • 在实际宽度为1440物理像素的屏幕上,1vp 约等于 3px(物理像素)

不同的设备屏幕的宽度 vp 是不一致的,那怎么适配呢?

  • 采用:伸缩布局,网格系统,栅格系统进行布局适配。
  • 伸缩 layoutWeight(flex: number) 占剩余空间多少份,可以理解成CSS的 flex: 1
@Entry
@Component
struct Index {
  build() {
    Row(){
      Text('left')
        .layoutWeight(1)
        .backgroundColor('red')
      Text('right')
        .layoutWeight(2)
        .backgroundColor('green')
    }
    .width('100%')
  }
}
  • 等比例,设置元素宽高比 aspectRatio(ratio: number)
@Entry
@Component
struct Index {
  build() {
    Text('left')
      .width('50%')
        // 宽高比例
      .aspectRatio(1)
      .backgroundColor('red')
  }
}

3. 样式-@Styles 复用

在开发过程中会出现大量代码在进行重复样式设置,@Styles 可以帮我们进行样式复用

// 全局
@Styles 
function functionName() { ... }

@Entry
@Component
sturt Index{
  // 组件内
  @Styles 
  functionName() { ... }

  build() {
    Text('Text')
      .functionName()
  }
}

4. 样式-@Extends 复用

@Extend 用于扩展原生组件样式,通过传参提供更灵活的样式复用

  • 使用 @Extend 装饰器修饰的函数只能是 全局
  • 函数可以进行 传参,如果参数是状态变量,状态更新后会刷新UI
  • 且参数可以是一个函数,实现复用事件且可处理不同逻辑
// 全局  原生组件                     参数
//  ↓     ↓                          ↓ 
@Extend(Text) function functionName(w: number) { 
  .width(w)
}

需求:把 Text 改成按钮样式,且绑定 click 事件执行不同逻辑

import promptAction from '@ohos.promptAction'

@Extend(Text) function myClick(color: string, cb: () => void) {
  .backgroundColor(color)
  .width(100)
  .height(50)
  .textAlign(TextAlign.Center)
  .borderRadius(25)
  .onClick(() => cb())
}

@Entry
@Component
struct Other {
  @State
  color: string = '#ccc'

  build() {
    Column({ space: 20 }) {
      Text('Text1')
        .myClick(this.color, () => {
          this.color = '#069'
        })
      Text('Text2')
        .myClick('green', () => {
          promptAction.showToast({ message: '做其他事~' })
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

5. 样式-多态

stateStyles() 可以依据组件的内部状态的不同,快速设置不同样式。

  • focused:获焦态。
  • normal:正常态。
  • pressed:按压态。
  • disabled:不可用态。
import promptAction from '@ohos.promptAction'

// 胶囊按钮
@Extend(Text)
function capsule(){
  .height(40)
  .borderRadius(20)
  .backgroundColor(Color.Gray)
  .padding({ left: 15, right: 15 })
  .margin({ bottom: 15 })
}

@Entry
@Component
struct Index {
  @State
  disabled: boolean = false
  @State
  focused: boolean = false

  build() {
    Column() {

      // Button TextInput 默认开启获取焦点,页面中默认第一个这样的元素获取焦点
      // Button 比较多限制,一个是默认开启获取焦点能看,二是禁用状态下样式无法修改
      // Button('Button').focusable(false)

      Text('toggle disabled:' + this.disabled)
        .capsule()
        .onClick(()=>{
          this.disabled = !this.disabled
        })
      Text('toggle focused:' + this.focused)
        .capsule()
        .onClick(()=>{
          this.focused = !this.focused
        })
      Text('clickMe')
        .capsule()
        .enabled(!this.disabled)
        .focusable(this.focused)
        .onClick(() => {
          promptAction.showToast({ message: 'click' })
        })
        .fontColor('#fff')
        .stateStyles({
          normal: {
            .backgroundColor(Color.Blue)
          },
          focused: {
            .backgroundColor(Color.Red)
          },
          disabled: {
            .backgroundColor(Color.Black)
          },
          pressed: {
            .backgroundColor(Color.Orange)
          }
        })
    }
  }
}

组件进阶

1. 组件-事件监听

事件监听用于响应用户与组件的交互(如点击、输入、按键等),并执行相应的逻辑。

关键属性/方法

事件类型 用途 绑定方式
onClick 点击按钮或区域时触发。 Button().onClick(() => { ... })
onChange 输入框内容变化时触发(如 TextInput)。 TextInput().onChange((value) => { ... })
onSubmit 输入框内容提交时触发(如回车键)。 TextInput().onSubmit(() => { ... })
onKeyEvent 监听物理按键(如音量键、电源键)。 Button().onKeyEvent((event) => { ... })
onKeyPreIme 优先级更高的按键监听(可拦截事件传递)。 Search().onKeyPreIme((event) => { ... })

示例代码

  • 示例1:输入框与按钮事件
import { promptAction } from '@kit.ArkUI'

@Entry
@Component
struct Test {
  @State username: string = ''

  build() {
    Column() {
      // 输入框内容变化监听
      TextInput({ placeholder: '输入用户名' })
        .onChange((value: string) => {
          this.username = value
        })
          // 输入框提交监听(如回车键)
        .onSubmit(() => {
          console.info('提交的用户名:' + this.username)
        })

      // 按钮点击监听
      Button('提交')
        .onClick(() => {
          if (this.username) {
            // promptAction.showToast({ message: '用户名:' + this.username })
            promptAction.showToast({ message: '用户名:' + this.username })
          }
        })
    }
  }
}
  • 示例2:物理按键监听(音量键)

在这里插入图片描述

import { KeyCode } from '@kit.InputKit'

@Entry
@Component
struct Test {
  @State volumeDownCount: number = 0

  build() {
    Column() {
      Text(`音量减键点击次数:${this.volumeDownCount}`)
        .fontSize(20)
        .padding(10)

      // 绑定按钮的onKeyEvent监听
      Button('监听音量键')
        .defaultFocus(true) // 获取焦点才能触发事件
        .onKeyEvent((event: KeyEvent) => {
          if (event.keyCode === KeyCode.KEYCODE_BRIGHTNESS_DOWN) {
            this.volumeDownCount++
          }
        })
    }
  }
}

2. 基础-组件状态

用途:通过状态管理实现UI与数据的动态绑定,状态变化时自动触发UI更新。

关键装饰器

装饰器 用途 适用场景
@State 定义组件内部的私有状态变量。 组件内部数据管理(如表单输入、计数器)
@LocalStorage 页面级临时存储(页面关闭后可能保留)。 表单草稿保存、页面数据缓存
@AppStorage 应用级全局状态(应用生命周期内有效)。 用户登录Token、主题配置

示例代码

  • 示例1:@State 简单数据
import { promptAction } from '@kit.ArkUI'

@Entry
@Component
struct Test {
  // 1.数据需要声明后才能使用,声明时需要标注类型
  // 2.数据改变后需要响应式更新到页面上,需要给数据添加@State修饰符
  @State username: string = ''
  @State password: string = ''

  build() {
    Column({space:10}) {
      // 用户名输入框
      TextInput({ placeholder: '用户名', text: this.username })
        .onChange((value: string) => {
          this.username = value // 更新状态
        })

      // 密码输入框
      TextInput({ placeholder: '密码', text: this.password})
        .onChange((value: string) => {
          this.password = value
        })

      // 登录按钮
      Button('登录')
        .onClick(() => {
          if (this.username === 'admin' && this.password === '123') {
            promptAction.showToast({ message: '登录成功!' })
          } else {
            promptAction.showToast({ message: '用户名或密码错误!' })
          }
        })
        .width('100%')
    }
    .padding(10)
    .width('100%')
  }
}

数据结构说明

类型分类 类型名称 示例 描述 备注
基本数据类型 string @State name: string = "张三" 字符串类型 支持单引号、双引号、模板字符串
number @State age: number = 25; 数字类型 不区分整型和浮点型
boolean @State isActive: boolean = true; 布尔类型 只有 true/false 两个值
null @State empty: null = null; 空值类型 需显式声明类型
undefined @State data: undefined = undefined; 未定义类型 通常用于未初始化的变量
引用数据类型 Object @State user: object = { name: "李四" } 对象类型 不推荐直接使用 object,建议用接口约束
Array @State names: Array<string> = [] 数组类型 支持泛型语法 Array
Function @State handler: () => void = () => {}; 函数类型 支持箭头函数类型注解
自定义类型 Interface typescript<br>interface Person {<br> name: string;<br> age?: number;<br>}<br> 接口(约束对象结构) ? 表示可选属性,支持继承和联合类型
Class typescript<br>class Student {<br> name: string = "未知";<br> study() {}<br>}<br> 类(包含属性和方法) 支持继承、静态成员、访问修饰符(public/private)
特殊类型 any let dynamicData: any = "可赋任意值"; 动态类型(绕过类型检查) 慎用,会失去类型安全
void function log(): void { console.log('...'); } 无返回值类型 常用于函数返回值
union let id: string I number = "1001"; 联合类型(多类型组合) 通过 I 符号组合
enum typescript<br>enum Color {<br> Red,<br> Green = 2<br>}<br> 枚举类型 支持数字/字符串枚举

3. 组件-双向绑定

界面渲染

1. 渲染-条件渲染

条件渲染可根据应用的不同状态,使用if、else和else if渲染对应状态下的UI内容。

@Entry
@Component
struct Index {

  @State
  loading: boolean = false

  build() {
    Column({ space: 20 }){
      if (this.loading) {
        LoadingProgress()
          .width(100)
          .height(100)
      } else  {
        Text('后台数据')
        Text('后台数据')
        Text('后台数据')
      }
      Button('更新数据')
        .onClick(() => {
          this.loading = true
          setTimeout(() => {
            this.loading = false
          }, 2000)
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

2. 渲染-循环渲染

ForEach 接口基于数组类型数据来进行循环渲染,需要与容器组件配合使用。

语法:

ForEach(
  // 数据源
  arr: Array,
  // 组件生成函数
  itemGenerator: (item: Array, index?: number) => void,
  // 键值生成函数
  keyGenerator?: (item: Array, index?: number): string => string
)

应用:

class User {
  id: string
  name: string
  age: number
}


@Entry
@Component
struct Index {
  @State
  userList: User[] = []

  build() {
    Scroll() {
      Column({ space: 20 }) {
        // 循环渲染
        ForEach(
          // 1. 数据源
          this.userList,
          // 2. 组件生成函数
          (item: User) => {
            // 内容
            Text(`${item.name} 今年 ${item.age}`)
          },
          // 3. 键值生成函数
          item => item.id
        )
        Button('加载更多')
          .onClick(() => {
            const arr: User[] = []
            for (let index = 0; index < 10; index++) {
              arr.push({ id: Math.random().toString(), name: 'jack', age: Math.ceil(Math.random() * 100) })
            }
            this.userList.push(...arr)
          })
      }
    }
    .width('100%')
  }
}

2. 状态管理

4. 美团外卖

5. 应用程序开发

6. 华为闹钟


网站公告

今日签到

点亮在社区的每一天
去签到