鸿蒙开发笔记(三):页面和自定义组件生命周期
先明确自定义组件和页面的关系:
-
自定义组件:@Component装饰的UI单元,可以组合多个系统组件实现UI的复用。
-
页面:即应用的UI页面。可以由一个或者多个自定义组件组成,@Entry装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有一个@Entry。只有被@Entry装饰的组件才可以调用页面的生命周期。
页面生命周期,即被@Entry装饰的组件生命周期,提供以下生命周期接口:
- onPageShow:页面每次显示时触发。
- onPageHide:页面每次隐藏时触发一次。
- onBackPress:当用户点击返回按钮时触发。
组件生命周期,即一般用@Component装饰的自定义组件的生命周期,提供以下生命周期接口:
-
aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
-
aboutToDisappear:在自定义组件即将析构销毁时执行。
生命周期流程如下图所示,下图展示的是被@Entry装饰的组件(首页)生命周期。

根据上面的流程图,我们从自定义组件的初始创建、重新渲染和删除来详细解释。
1. 自定义组件的创建和渲染流程
-
自定义组件的创建:自定义组件的实例由ArkUI框架创建。
-
初始化自定义组件的成员变量:通过本地默认值或者构造方法传递参数来初始化自定义组件的成员变量,初始化顺序为成员变量的定义顺序。
-
如果开发者定义了aboutToAppear,则执行aboutToAppear方法。
-
在首次渲染的时候,执行build方法渲染系统组件,如果子组件为自定义组件,则创建自定义组件的实例。在执行build()函数的过程中,框架会观察每个状态变量的读取状态,将保存两个map:
a. 状态变量 -> UI组件(包括ForEach和if)。
b. UI组件 -> 此组件的更新函数,即一个lambda方法,作为build()函数的子集,创建对应的UI组件并执行其属性方法,示意如下。
build() {...this.observeComponentCreation(() => {Button.create();})this.observeComponentCreation(() => {Text.create();})...
}
当应用在后台启动时,此时应用进程并没有销毁,所以仅需要执行onPageShow。
2. 自定义组件重新渲染
当事件句柄被触发(比如设置了点击事件,即触发点击事件)改变了状态变量时,或者LocalStorage / AppStorage中的属性更改,并导致绑定的状态变量更改其值时:
-
框架观察到了变化,将启动重新渲染。
-
根据框架持有的两个map(自定义组件的创建和渲染流程中第4步),框架可以知道该状态变量管理了哪些UI组件,以及这些UI组件对应的更新函数。执行这些UI组件的更新函数,实现最小化更新。
3. 自定义组件的删除
如果if组件的分支改变,或者ForEach循环渲染中数组的个数改变,组件将被删除:
-
在删除组件之前,将调用其aboutToDisappear生命周期函数,标记着该节点将要被销毁。ArkUI的节点删除机制是:后端节点直接从组件树上摘下,后端节点被销毁,对前端节点解引用,当前端节点已经没有引用时,将被JS虚拟机垃圾回收。
-
自定义组件和它的变量将被删除,如果其有同步的变量,比如@Link、@Prop、@StorageLink,将从同步源上取消注册。
不建议在生命周期aboutToDisappear内使用async await,如果在生命周期的aboutToDisappear使用异步操作(Promise或者回调方法),自定义组件将被保留在Promise的闭包中,直到回调方法被执行完,这个行为阻止了自定义组件的垃圾回收。
以下示例展示了生命周期的调用时机:
// Index.ets
import router from '@ohos.router';@Entry
@Component
struct MyComponent {@State showChild: boolean = true;// 只有被@Entry装饰的组件才可以调用页面的生命周期onPageShow() {console.info('Index onPageShow');}// 只有被@Entry装饰的组件才可以调用页面的生命周期onPageHide() {console.info('Index onPageHide');}// 只有被@Entry装饰的组件才可以调用页面的生命周期onBackPress() {console.info('Index onBackPress');}// 组件生命周期aboutToAppear() {console.info('MyComponent aboutToAppear');}// 组件生命周期aboutToDisappear() {console.info('MyComponent aboutToDisappear');}build() {Column() {// this.showChild为true,创建Child子组件,执行Child aboutToAppearif (this.showChild) {Child()}// this.showChild为false,删除Child子组件,执行Child aboutToDisappearButton('create or delete Child').onClick(() => {this.showChild = false;})// push到Page2页面,执行onPageHideButton('push to next page').onClick(() => {router.pushUrl({ url: 'pages/Page2' });})}}
}@Component
struct Child {@State title: string = 'Hello World';// 组件生命周期aboutToDisappear() {console.info('[lifeCycle] Child aboutToDisappear')}// 组件生命周期aboutToAppear() {console.info('[lifeCycle] Child aboutToAppear')}build() {Text(this.title).fontSize(50).onClick(() => {this.title = 'Hello ArkUI';})}
}
以上示例中,Index页面包含两个自定义组件,一个是被@Entry装饰的MyComponent,也是页面的入口组件,即页面的根节点;一个是Child,是MyComponent的子组件。只有@Entry装饰的节点才可以生效页面的生命周期方法,所以MyComponent中声明了当前Index页面的页面生命周期函数。MyComponent和其子组件Child也同时也声明了组件的生命周期函数。
-
应用冷启动的初始化流程为:MyComponent aboutToAppear --> MyComponent build --> Child aboutToAppear --> Child build --> Child build执行完毕 --> MyComponent build执行完毕 --> Index onPageShow。
-
点击“delete Child”,if绑定的this.showChild变成false,删除Child组件,会执行Child aboutToDisappear方法。
-
点击“push to next page”,调用router.pushUrl接口,跳转到另外一个页面,当前Index页面隐藏,执行页面生命周期Index onPageHide。此处调用的是router.pushUrl接口,Index页面被隐藏,并没有销毁,所以只调用onPageHide。跳转到新页面后,执行初始化新页面的生命周期的流程。
-
如果调用的是router.replaceUrl,则当前Index页面被销毁,执行的生命周期流程将变为:Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。上文已经提到,组件的销毁是从组件树上直接摘下子树,所以先调用父组件的aboutToDisappear,再调用子组件的aboutToDisappear,然后执行初始化新页面的生命周期流程。
-
点击返回按钮,触发页面生命周期Index onBackPress,且触发返回一个页面后会导致当前Index页面被销毁。
-
最小化应用或者应用进入后台,触发Index onPageHide。当前Index页面没有被销毁,所以并不会执行组件的aboutToDisappear。应用回到前台,执行Index onPageShow。
-
退出应用,执行Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。
相关文章:
鸿蒙开发笔记(三):页面和自定义组件生命周期
先明确自定义组件和页面的关系: 自定义组件:Component装饰的UI单元,可以组合多个系统组件实现UI的复用。 页面:即应用的UI页面。可以由一个或者多个自定义组件组成,Entry装饰的自定义组件为页面的入口组件,…...
报名活动怎么做_小程序创建线上报名活动最详细攻略
报名活动怎么做:一篇让你掌握活动策划与营销的秘籍 在当今社会,无论是线上还是线下,活动已经成为企业营销和品牌推广的重要手段。但是,如何策划一场成功的活动呢?这篇文章将为你揭示活动策划与营销的秘籍,…...
Apache POI 导出Excel报表
大家好我是苏麟 , 今天聊聊Apache POI . Apache POI 介绍 Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下,POI 都是用于操作 E…...
使用Qt连接scrcpy-server控制手机
Qt连接scrcpy-server 测试环境如何启动scrcpy-server1. 连接设备2. 推送scrcpy-server到手机上3. 建立Adb隧道连接4. 启动服务5. 关闭服务 使用QTcpServer与scrcpy-server建立连接建立连接并视频推流完整流程1. 开启视频推流过程2. 关闭视频推流过程 视频流的解码1. 数据包协议…...
debian12部署Gitea服务之二——部署git-lfs
Debian安装gitlfs: 先更新下软件包版本 sudo apt update 安装 sudo apt install git-lfs 验证是否安装成功 git lfs version cd到Gitea仓库目录下 cd /mnt/HuHDD/Git/Gitea/Repo/hu/testrepo.git 执行lfs的初始化命令 git lfs install客户机Windows端在官网下载并安装Git-Lfs 再…...
leetcode 1两数之和
题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺…...
C++多线程学习[三]:成员函数作为线程入口
一、成员函数作为线程入口 #include<iostream> #include<thread> #include<string>using namespace std;class Mythread { public:string str;void Test(){cout << str << endl;} }; int main() {Mythread test;test.str "Test";thr…...
移动硬盘无法识别处理办法
今天这里做一下总结,我现在手上有一个移动硬盘,插入win10电脑是有盘号的,但是 但是点击就出问题 解决办法 安装DiskGenius 下载网址在https://www.diskgenius.cn/download.php 下载之后解压安装就行,非常简单,然后…...
【Spring Cloud】Sentinel流量限流和熔断降级的讲解
🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《Spring Cloud》。🎯🎯 &am…...
前端浮点和16进制互转
一、浮点转16进制数据 //浮点数转16进制 function singleToHex(t) {if (t "") {return "";}t parseFloat(t.substr(0, 4));if (isNaN(t) true) {return "Error";}if (t 0) {return "00000000";}var s,e,m;if (t > 0) {s 0;}e…...
Java中hashCode()与equals()的相关规定
API文件有对对象的状态制定出必须遵循的规则。hashCode()和equals()是object中定义的两个方法,它们都与对象的相等性有关。 通常情况下我们需要同时使用这两个方法来判断两个对象是否相等,只有两个对象的equals()方法返回true,并且它们的has…...
转行做鸿蒙开发首先需要学习哪些?
随着越来越多的企业和团队开始布局鸿蒙生态,鸿蒙开发人才的需求也呈现出井喷式的增长。对于开发者而言,掌握鸿蒙开发技能不仅意味着能够抓住这个千载难逢的机遇,更意味着能够在未来的科技竞争中占据先机。 在这个变革的时代,鸿蒙开…...
8x8离散余弦的快速精确实现使用数据流单指令多数据扩展指令集进行转换MMX 说明书
1.https://www.cs.cmu.edu/~barbic/cs-740/ap922.pdf 2.FFmpeg: libavcodec/x86/fdct.c Source File 再学FDCT快速精确实现协议改写浮点FDCT, ffmpeg的dct使用的就是这个快速精确协议。 3.http://dspace.fcu.edu.tw/bitstream/2377/30265/1/ICM%204-1.pdf 我想如把所有余弦…...
微信公众号注册(详细图文教程)
目录 一、公众号注册准备1.1 准备事项1.2 个人注册1.3 企业注册 二、公众号注册2.1 基本信息填写2.2 选择类型2.3 信息登记2.4 公众号信息2.5 修改头像2.6 自动回复消息 三、总结 一、公众号注册准备 1.1 准备事项 公众号名称:公众号名称可以由中文、英文、数字、…...
排序算法-冒泡排序(含C语言代码示例)
一、算法介绍 冒泡排序是一种简单的排序算法,其核心思想是重复地遍历待排序列表,比较并交换相邻元素,使得较大的元素逐渐“冒泡”到列表的末尾,而较小的元素则逐渐上浮至列表的前端。该算法的名字源于类比元素的移动过程ÿ…...
易基因:表观遗传学和表观转录组修饰在植物金属和准金属暴露中的作用 | 抗逆综述
大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 非必需金属(non-essential metal)和准金属(metalloid,也称类金属)对土壤的污染是全球许多地区面临的严重问题。这些非必需金属…...
使用Guava Retrying优雅的实现业务异常重试
上次写过一篇如何使用spring retry来实现业务重试的文章:https://blog.csdn.net/Kingsea442/article/details/135341747 尽管 Spring Retry 工具能够优雅地实现重试,但它仍然存在两个不太友好的设计: 重试实体被限定为 Throwable 子类&#…...
java SSM物业管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计
一、源码特点 java SSM物业管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和 数据库,系统主要采用B/…...
Hive使用shell调用命令行特殊字符处理
1.场景分析 数据处理常用hive -e的方式,通过脚本操作数仓,过程中常常遇到特殊字符的处理,如单双引号、反斜杠、换行符等,现将特殊字符用法总结使用如下,可直接引用,避免自行测试的繁琐。 2.特殊字符处理 …...
服务器里面很卡,打开文件卡住了一般是什么问题,怎么解决
随着互联网业务的快速发展,各项业务都绕不开服务器。在日常使用中,服务器有着非常重要的作用。而我们日常使用中,也会遇到各种各样的问题。最近就有遇到用户联系咨询德迅云安全,询问自己服务器突然很卡,打开文件都卡住…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
在Zenodo下载文件 用到googlecolab googledrive
方法:Figshare/Zenodo上的数据/文件下载不下来?尝试利用Google Colab :https://zhuanlan.zhihu.com/p/1898503078782674027 参考: 通过Colab&谷歌云下载Figshare数据,超级实用!!࿰…...
VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...
