目录
(二)LocalStorage / AppStorage 属性更改
一、引言
在鸿蒙应用开发的广袤天地中,ArkUI 无疑是一颗璀璨的明星,占据着举足轻重的地位。它作为鸿蒙系统应用界面的 UI 开发框架,宛如一座桥梁,连接着开发者的创意与用户的体验。ArkUI 为开发者们提供了简洁自然的 UI 声明式语法,就像赋予了开发者们一支神奇的画笔,能够轻松勾勒出精美的界面;丰富多样的 UI 组件库,如同一个装满各种工具的百宝箱,满足各种界面构建需求;强大且灵活的动画与交互机制,更是为应用注入了灵魂,让用户与应用之间的互动变得妙趣横生。
在实际的开发过程中,自定义组件是开发者们施展拳脚、实现个性化功能和独特界面设计的重要手段。然而,其中的重新渲染机制,却像是隐藏在幕后的神秘角色,虽不常被直接感知,却对应用的性能、用户体验以及开发效率有着深远的影响。想象一下,用户在使用应用时,每一次界面的更新、交互的反馈,如果不能流畅地呈现,就如同看一场卡顿的电影,再好的剧情也会大打折扣。理解自定义组件重新渲染的原理和机制,对于开发者来说,就如同掌握了开启高效开发和优质应用体验大门的钥匙。它不仅能帮助我们优化应用性能,避免不必要的资源浪费,还能让我们更加得心应手地处理各种复杂的业务场景,打造出更加流畅、稳定且富有创意的应用。
二、ArkUI 自定义组件基础
(一)自定义组件概念
在 ArkUI 的世界里,自定义组件就像是搭建高楼大厦的基石,是构建复杂用户界面的基础单元 。它允许开发者将一系列相关的 UI 元素和逻辑封装在一起,形成一个独立的、可复用的模块。通过自定义组件,开发者能够将复杂的界面拆分成一个个功能明确的小部分,实现代码的高度复用和逻辑的清晰分离,就如同将一个大型工程分解为多个小型的、易于管理的子项目,大大提高了开发效率和代码的可维护性。例如,在一个电商应用中,商品展示模块、购物车模块、用户信息模块等都可以被封装成自定义组件,在不同的页面和场景中重复使用,不仅减少了代码的冗余,还使得整个应用的结构更加清晰、易于理解和修改。
(二)组件的创建与使用
接下来,我们通过一个简单的代码示例,来揭开自定义组件创建与使用的神秘面纱。假设我们要创建一个简单的自定义按钮组件,代码如下:
// 定义一个名为MyButton的自定义组件
@Component
struct MyButton {
// 按钮的文本内容
@Prop text: string;
// 按钮的点击事件处理函数
@Event onClick: () => void;
build() {
// 使用Row容器组件来布局
Row() {
// 创建一个Text组件来显示按钮文本
Text(this.text)
.fontSize(16)
.fontColor(Color.White)
.backgroundColor(Color.Blue)
.padding(10)
.onClick(() => {
// 当按钮被点击时,调用传入的点击事件处理函数
this.onClick();
});
}
}
}
在上述代码中,我们首先使用@Component装饰器将一个结构体MyButton声明为一个自定义组件。这个组件包含两个重要的部分:一个是@Prop装饰的text属性,用于接收外部传入的按钮文本内容;另一个是@Event装饰的onClick属性,用于接收外部传入的点击事件处理函数。在build函数中,我们使用Row容器组件和Text组件来构建按钮的 UI 界面,并为Text组件添加了样式和点击事件处理逻辑。
那么,如何在页面中引入和使用这个自定义组件呢?假设我们有一个主页面组件MainPage,代码如下:
@Entry
@Component
struct MainPage {
// 定义一个计数器变量
@State count: number = 0;
// 定义按钮点击事件处理函数
handleClick() {
this.count++;
}
build() {
Column() {
// 引入并使用MyButton自定义组件
MyButton({
text: `点击次数: ${this.count}`,
onClick: this.handleClick.bind(this)
})
}
}
}
在MainPage组件中,我们首先定义了一个状态变量count用于记录按钮的点击次数,以及一个handleClick函数用于处理按钮的点击事件。在build函数中,我们通过MyButton({...})的方式引入并使用了自定义组件MyButton,并为其传入了text和onClick属性的值。当用户点击按钮时,handleClick函数会被调用,count变量的值会增加,同时按钮的文本也会随之更新,展示出最新的点击次数。
三、重新渲染机制核心原理
(一)状态管理与 UI 渲染关系
在声明式 UI 编程的广阔领域中,有一个核心的理念贯穿始终:UI 是程序状态的直观反映。就如同镜子一般,程序状态的任何风吹草动,都会在 UI 上清晰地映照出来。当程序状态发生变化时,UI 就会如同被一只无形的手推动,自动进行重新渲染,以展示出最新的状态信息。这种紧密的联系,使得开发者能够将更多的精力聚焦在业务逻辑和状态的管理上,而无需为 UI 的更新细节而烦恼。
在 ArkUI 中,状态管理就像是整个应用的 “指挥中心”,发挥着至关重要的作用。它负责对应用的各种状态进行集中管理和协调,确保状态的变化能够被准确地捕捉和处理 。通过状态管理机制,开发者可以轻松地定义、修改和监听应用状态,实现 UI 与状态之间的高效同步。例如,在一个实时数据展示的应用中,通过状态管理,当后台数据更新时,对应的状态变量会随之改变,进而触发 UI 的重新渲染,将最新的数据呈现给用户,让用户能够及时获取到关键信息。
(二)@State 修饰符详解
在 ArkUI 的状态管理体系中,@State修饰符是一个不可或缺的重要角色,它就像是一把神奇的钥匙,能够开启组件内部状态管理的大门。@State修饰符主要用于将组件内的变量标记为状态变量,这些被标记的变量就如同拥有了特殊的 “魔力”,成为了组件内部状态数据的承载者。当这些状态数据发生任何修改时,就如同触发了一个连锁反应,将会自动调用所在组件的build方法,从而实现 UI 的刷新,让用户能够实时看到界面的变化。
@State修饰的变量具有一些独特而重要的特性。它与子组件中的@Prop装饰变量之间建立起了单向数据同步的桥梁,数据从父组件流向子组件,就像一条单向的河流,父组件的状态变化可以传递给子组件,但子组件无法直接修改父组件的状态。而与@Link、@ObjectLink装饰变量之间则建立起了双向数据同步的通道,数据可以在组件之间自由地双向流动,实现了更加灵活的数据交互。@State修饰的变量生命周期与其所属自定义组件的生命周期紧密相连,同生共死。当组件被创建时,@State变量也随之诞生;当组件被销毁时,@State变量也会随之消失,这种紧密的绑定关系确保了状态数据的一致性和稳定性。
在使用@State修饰符时,也有一些使用限制需要我们特别注意。@State装饰的变量必须在声明时进行初始化,不能为空值,这就像是给一个容器赋予了初始的内容,确保它在使用时不会为空。@State支持多种数据类型,如object、class、string、number、boolean、enum类型以及这些类型的数组,但不支持any类型,也不支持简单类型和复杂类型的联合类型,同时严格禁止使用undefined和null。此外,需要注意的是,@State标记的属性是私有变量,如同被藏在一个秘密的宝箱中,只能在组件内访问,外部无法直接窥探和修改,这为组件的状态管理提供了一定的安全性和封装性。
(三)状态变量与组件渲染的映射
当组件首次渲染时,框架会像一个细心的记录员,默默地记录下状态变量与组件之间的映射关系。它会仔细地梳理每个状态变量与哪些组件的显示和行为密切相关,将这些关系一一记录在案,形成一个清晰的映射表。这个映射表就像是一张详细的地图,为后续的重新渲染提供了关键的指引。
在重新渲染的过程中,这个映射关系就像是一个精准的导航仪,发挥着重要的驱动作用。当状态变量发生变化时,框架会迅速根据之前记录的映射关系,准确地定位到受该状态变量影响的相关组件。然后,框架会有条不紊地执行这些组件的更新函数,对组件进行最小化的更新,就像精心修剪树木一样,只对需要改变的部分进行调整,而不会影响其他无关的部分。通过这种方式,实现了 UI 的高效更新,既保证了界面能够及时反映状态的变化,又最大限度地减少了不必要的计算和渲染开销,提高了应用的性能和响应速度。例如,在一个包含多个列表项的列表组件中,当某个列表项的状态变量发生变化时,框架能够根据映射关系,准确地找到对应的列表项组件进行更新,而不会对其他列表项造成干扰,确保了整个列表的稳定和高效展示。