鸿蒙ArkTS基础知识-自定义组件生命周期函数onBackPress的调用。

介绍

本课程使用声明式语法和组件化基础知识,搭建一个可刷新的排行榜页面。在排行榜页面中,使用循环渲染控制语法来实现列表数据渲染,使用@Builder创建排行列表布局内容,使用装饰器@State、@Prop、@Link来管理组件状态。最后我们点击系统返回按键,来学习自定义组件生命周期函数。效果如图所示:

相关概念

1.渲染控制语法:

  • 条件渲染:使用if/else进行条件渲染。语法如下:

    Column() {
    if (this.count > 0) {
    Text('count is positive')
    }
    }

  • 循环渲染:开发框架提供循环渲染(ForEach组件)来迭代数组,并为每个数组项创建相应的组件。ForEach定义如下:

    ForEach(
    arr: any[], // 用于迭代的数组
    itemGenerator: (item: any, index?: number) => void, // 生成子组件的lambda函数
    keyGenerator?: (item: any, index?: number) => string // 用于给定数组项生成唯一且稳定的键值
    )

2.组件状态管理装饰器和@Builder装饰器:

组件状态管理装饰器用来管理组件中的状态,它们分别是:@State、@Prop、@Link。

  • @State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。
  • @Prop与@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但更改不会通知给父组件,即@Prop属于单向数据绑定。
  • @Link装饰的变量可以和父组件的@State变量建立双向数据绑定,需要注意的是:@Link变量不能在组件内部进行初始化。
  • @Builder装饰的方法用于定义组件的声明式UI描述,在一个自定义组件内快速生成多个布局内容。

@State、@Prop、@Link三者关系如图所示:

3.组件生命周期函数:

自定义组件的生命周期函数用于通知用户该自定义组件的生命周期,这些回调函数是私有的,在运行时由开发框架在特定的时间进行调用,不能从应用程序中手动调用这些回调函数。 右图是自定义组件生命周期的简化图示:

说明: 需要注意的是,部分生命周期回调函数仅对**@Entry**修饰的自定义组件生效,它们分别是:onPageShow、onPageHide、onBackPress。

环境搭建

软件要求

  • DevEco Studio版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:润和RK3568开发板。
  • OpenHarmony系统:3.2 Release。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2 Release版本为例:

2.搭建烧录环境。

  1. 完成DevEco Device Tool的安装
  2. 完成RK3568开发板的烧录

3.搭建开发环境。

  1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
  2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择"Empty Ability")。
  3. 工程创建完成后,选择使用真机进行调测。

代码结构解读

本篇Codelab只对核心代码进行讲解。

├──entry/src/main/ets               // 代码区    
│  ├──common                        // 公共文件目录
│  │  └──constants                  
│  │     └──Constants.ets           // 常量
│  ├──entryability
│  │  └──EntryAbility.ts            // 应用的入口
│  ├──model                         
│  │  └──DataModel.ets              // 模拟数据
│  ├──pages
│  │  └──RankPage.ets               // 入口页面
│  ├──view                          // 自定义组件目录
│  │  ├──ListHeaderComponent.ets
│  │  ├──ListItemComponent.ets
│  │  └──TitleComponent.ets
│  └──viewmodel         
│     ├──RankData.ets               // 实体类            
│     └──RankViewModel.ets          // 视图业务逻辑类
└──entry/src/main/resources         // 资源文件目录

使用@Link封装标题组件

在TitleComponent文件中,首先使用struct对象创建自定义组件,然后使用@Link修饰器管理TitleComponent组件内的状态变量isRefreshData,状态变量isRefreshData值发生改变后,通过@Link装饰器通知页面刷新List中的数据。代码如下:

// TitleComponent.ets
...
@Component
export struct TitleComponent {
  @Link isRefreshData: boolean; // 判断是否刷新数据
  @State title: Resource = $r('app.string.title_default');

  build() {
    Row() {
      ...
      Row() {
        Image($r('app.media.loading'))
          .height(TitleBarStyle.IMAGE_LOADING_SIZE)
          .width(TitleBarStyle.IMAGE_LOADING_SIZE)
          .onClick(() => {
            this.isRefreshData = !this.isRefreshData;
          })
      }
      .width(TitleBarStyle.WEIGHT)
      .height(WEIGHT)
      .justifyContent(FlexAlign.End)
    }
   ...
  }
}

效果如图所示:

封装列表头部样式组件

在ListHeaderComponent文件中,我们使用常规成员变量来设置自定义组件ListHeaderComponent的widthValue和paddingValue,代码如下:

// ListHeaderComponent.ets
...
@Component
export struct ListHeaderComponent {
  paddingValue: Padding | Length = 0;
  widthValue: Length = 0;

  build() {
    Row() {
      Text($r('app.string.page_number'))
        .fontSize(FontSize.SMALL)
        .width(ListHeaderStyle.LAYOUT_WEIGHT_LEFT)
        .fontWeight(ListHeaderStyle.FONT_WEIGHT)
        .fontColor($r('app.color.font_description'))
      Text($r('app.string.page_type'))
        .fontSize(FontSize.SMALL)
        .width(ListHeaderStyle.LAYOUT_WEIGHT_CENTER)
        .fontWeight(ListHeaderStyle.FONT_WEIGHT)
        .fontColor($r('app.color.font_description'))
      Text($r('app.string.page_vote'))
        .fontSize(FontSize.SMALL)
        .width(ListHeaderStyle.LAYOUT_WEIGHT_RIGHT)
        .fontWeight(ListHeaderStyle.FONT_WEIGHT)
        .fontColor($r('app.color.font_description'))
    }
    .width(this.widthValue)
    .padding(this.paddingValue)
  }
}

效果如图所示:

创建ListItemComponent

为了体现@Prop单向绑定功能,我们在ListItemComponent组件中添加了一个@Prop修饰的字段isSwitchDataSource,当通过点击改变ListItemComponent组件中isSwitchDataSource状态时,ListItemComponent作为List的子组件,并不会通知其父组件List刷新状态。

在代码中,我们使用@State管理ListItemComponent中的 isChange 状态,当用户点击ListItemComponent时,ListItemComponent组件中的文本颜色发生变化。我们使用条件渲染控制语句,创建的圆型文本组件。

// ListItemComponent.ets
...
@Component
export struct ListItemComponent {
  index?: number;
  private name?: Resource;
  @Prop vote: string = '';
  @Prop isSwitchDataSource: boolean = false;
  // 判断是否改变ListItemComponent字体颜色
  @State isChange: boolean = false;

  build() {
    Row() {
      Column() {
        if (this.isRenderCircleText()) {
          if (this.index !== undefined) {
            this.CircleText(this.index);
          }
        } else {
          Text(this.index?.toString())
            .lineHeight(ItemStyle.TEXT_LAYOUT_SIZE)
            .textAlign(TextAlign.Center)
            .width(ItemStyle.TEXT_LAYOUT_SIZE)
            .fontWeight(FontWeight.BOLD)
            .fontSize(FontSize.SMALL)
        }
      }
      .width(ItemStyle.LAYOUT_WEIGHT_LEFT)
      .alignItems(HorizontalAlign.Start)

      Text(this.name)
        .width(ItemStyle.LAYOUT_WEIGHT_CENTER)
        .fontWeight(FontWeight.BOLDER)
        .fontSize(FontSize.MIDDLE)
        .fontColor(this.isChange ? ItemStyle.COLOR_BLUE : ItemStyle.COLOR_BLACK)
      Text(this.vote)
        .width(ItemStyle.LAYOUT_WEIGHT_RIGHT)
        .fontWeight(FontWeight.BOLD)
        .fontSize(FontSize.SMALL)
        .fontColor(this.isChange ? ItemStyle.COLOR_BLUE : ItemStyle.COLOR_BLACK)
    }
    .height(ItemStyle.BAR_HEIGHT)
    .width(WEIGHT)
    .onClick(() => {
      this.isSwitchDataSource = !this.isSwitchDataSource;
      this.isChange = !this.isChange;
    })
  }
  ...
}

效果如图所示:

创建RankList

为了简化代码,提高代码的可读性,我们使用@Builder描述排行列表布局内容,使用循环渲染组件ForEach创建ListItem。代码如下:

// RankPage.ets
...
  build() {
    Column() {
      // 顶部标题组件
      TitleComponent({ isRefreshData: $isSwitchDataSource, title: TITLE })
      // 列表头部样式
      ListHeaderComponent({
        paddingValue: {
          left: Style.RANK_PADDING,
          right: Style.RANK_PADDING
        },
        widthValue: Style.CONTENT_WIDTH
      })
      .margin({
        top: Style.HEADER_MARGIN_TOP,
        bottom: Style.HEADER_MARGIN_BOTTOM
      })
      // 列表区域
      this.RankList(Style.CONTENT_WIDTH)
    }
    .backgroundColor($r('app.color.background'))
    .height(WEIGHT)
    .width(WEIGHT)
  }

  @Builder RankList(widthValue: Length) {
    Column() {
      List() {
        ForEach(this.isSwitchDataSource ? this.dataSource1 : this.dataSource2,
          (item: RankData, index?: number) => {
            ListItem() {
              ListItemComponent({ index: (Number(index) + 1), name: item.name, vote: item.vote,
                isSwitchDataSource: this.isSwitchDataSource
              })
            }
          }, (item: RankData) => JSON.stringify(item))
      }
      .width(WEIGHT)
      .height(Style.LIST_HEIGHT)
      .divider({ strokeWidth: Style.STROKE_WIDTH })
    }
    .padding({
      left: Style.RANK_PADDING,
      right: Style.RANK_PADDING
    })
    .borderRadius(Style.BORDER_RADIUS)
    .width(widthValue)
    .alignItems(HorizontalAlign.Center)
    .backgroundColor(Color.White)
  }
...

效果如图所示:

使用自定义组件生命周期函数

我们通过点击系统导航返回按钮来演示onBackPress回调方法的使用,在指定的时间段内,如果满足退出条件,onBackPress将返回false,系统默认关闭当前页面。否则,提示用户需要再点击一次才能退出,同时onBackPress返回true,表示用户自己处理导航返回事件。代码如下:

// RankPage.ets
... 
@Entry
@Component
struct RankPage {
  ...
  onBackPress() {
    if (this.isShowToast()) {
      prompt.showToast({
        message: $r('app.string.prompt_text'),
        duration: TIME
      });
      this.clickBackTimeRecord = new Date().getTime();
      return true;
    }
    return false;
  }
  ...
}

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. 条件渲染、循环渲染语法的使用。
  2. @State、@Prop、@Link修饰器的使用。
  3. @Builder修饰器的使用。
  4. 自定义组件生命周期函数onBackPress的调用。

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完整版方式请点击→《HarmonyOS教学视频

HarmonyOS教学视频:语法ArkTS、TypeScript、ArkUI等.....视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取完整版白皮书请点击→《鸿蒙生态应用开发白皮书V2.0PDF

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. ......

二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全
  5. ........

三、如何快速入门?《做鸿蒙应用开发到底学习些啥?

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ......

四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ......

五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ......

更多了解更多鸿蒙开发的相关知识 可以参考:****《鸿蒙 (Harmony OS)开发学习手册

相关推荐
zhongcx2 小时前
鸿蒙应用示例:DevEco Testing 工具的常用功能及使用场景
harmonyos
@海~涛4 小时前
鸿蒙OpenHarmony
华为·harmonyos
zhongcx9 小时前
鸿蒙应用示例:镂空效果实现教程
harmonyos
训山10 小时前
【11】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-模块化语法与自定义组件
笔记·学习·华为·harmonyos·鸿蒙系统
helloxmg11 小时前
鸿蒙harmonyos next flutter混合开发之开发package
flutter·华为·harmonyos
zhongcx1 天前
鸿蒙应用示例:ArkTS UI框架中的文本缩进技巧
harmonyos
东林知识库1 天前
鸿蒙NEXT开发-自定义构建函数(基于最新api12稳定版)
华为·harmonyos
裴云飞1 天前
鸿蒙性能优化之布局优化
性能优化·harmonyos
zhongcx1 天前
鸿蒙应用示例:ArkTS中设置颜色透明度与颜色渐变方案探讨
harmonyos
真正的醒悟2 天前
华为资源分享
运维·服务器·华为