首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

鸿蒙HarmonyOS开发框架—学习ArkTS语言(状态管理 一)

  • 25-02-22 03:20
  • 2192
  • 12418
blog.csdn.net

状态管理概述

在前文的描述中,我们构建的页面多为静态界面。如果希望构建一个动态的、有交互的界面,就需要引入“状态”的概念。

图1 效果图

上面的示例中,用户与应用程序的交互触发了文本状态变更,状态变更引起了UI渲染,UI从“Hello World”变更为“Hello ArkUI”。

在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个UI模型,其中应用的运行时的状态是参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制。

自定义组件拥有变量,变量必须被装饰器装饰才可以成为状态变量,状态变量的改变会引起UI的渲染刷新。如果不使用状态变量,UI只能在初始化时渲染,后续将不会再刷新。 下图展示了State和View(UI)之间的关系。

  • View(UI):UI渲染,一般指自定义组件的build方法和@Builder装饰的方法内的UI描述。
  • State:状态,一般指的是装饰器装饰的数据。用户通过触发组件的事件方法,改变状态数据。状态数据的改变,引起UI的重新渲染。
基本概念
  • 状态变量:被状态装饰器装饰的变量,改变会引起UI的渲染更新。
  • 常规变量:没有状态的变量,通常应用于辅助计算。它的改变永远不会引起UI的刷新。
  • 数据源/同步源:状态变量的原始来源,可以同步给不同的状态数据。通常意义为父组件传给子组件的数据。
  • 命名参数机制:父组件通过指定参数传递给子组件的状态变量,为父子传递同步参数的主要手段。示例:CompA: ({ aProp: this.aProp })。
  • 从父组件初始化:父组件使用命名参数机制,将指定参数传递给子组件。本地初始化的默认值在有父组件传值的情况下,会被覆盖。示例:
  1. @Component
  2. struct MyComponent {
  3. @State count: number = 0;
  4. private increaseBy: number = 1;
  5. build() {
  6. }
  7. }
  8. @Component
  9. struct Parent {
  10. build() {
  11. Column() {
  12. // 从父组件初始化,覆盖本地定义的默认值
  13. MyComponent({ count: 1, increaseBy: 2 })
  14. }
  15. }
  16. }

复制

  • 初始化子节点:组件中状态变量可以传递给子组件,初始化子组件对应的状态变量。示例同上。
  • 本地初始化:变量声明的时候赋值,作为初始化的默认值。示例:@State count: number = 0。
装饰器总览

ArkUI提供了多种装饰器,通过使用这些装饰器,状态变量不仅可以观察在组件内的改变,还可以在不同组件层级间传递,比如父子组件、跨组件层级,也可以观察全局范围内的变化。根据状态变量的影响范围,将所有的装饰器可以大致分为:

  • 管理组件拥有状态的装饰器:组件级别的状态管理,可以观察组件内变化,和不同组件层级的变化,但需要唯一观察同一个组件树上,即同一个页面内。
  • 管理应用拥有状态的装饰器:应用级别的状态管理,可以观察不同页面,甚至不同UIAbility的状态变化,是应用内全局的状态管理。

从数据的传递形式和同步类型层面看,装饰器也可分为:

  • 只读的单向传递;
  • 可变更的双向传递。

图示如下,具体装饰器的介绍,可详见管理组件拥有的状态和管理应用拥有的状态。开发者可以灵活地利用这些能力来实现数据和UI的联动。

​

上图中,Components部分的装饰器为组件级别的状态管理,Application部分为应用的状态管理。开发者可以通过@StorageLink/@LocalStorageLink和@StorageProp/@LocalStorageProp实现应用和组件状态的双向和单向同步。图中箭头方向为数据同步方向,单箭头为单向同步,双箭头为双向同步。

管理组件拥有的状态,即图中Components级别的状态管理:

  • @State:@State装饰的变量拥有其所属组件的状态,可以作为其子组件单向和双向同步的数据源。当其数值改变时,会引起相关组件的渲染刷新。
  • @Prop:@Prop装饰的变量可以和父组件建立单向同步关系,@Prop装饰的变量是可变的,但修改不会同步回父组件。
  • @Link:@Link装饰的变量和父组件构建双向同步关系的状态变量,父组件会接受来自@Link装饰的变量的修改的同步,父组件的更新也会同步给@Link装饰的变量。
  • @Provide/@Consume:@Provide/@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量,可以不需要通过参数命名机制传递,通过alias(别名)或者属性名绑定。
  • @Observed:@Observed装饰class,需要观察多层嵌套场景的class需要被@Observed装饰。单独使用@Observed没有任何作用,需要和@ObjectLink、@Prop连用。
  • @ObjectLink:@ObjectLink装饰的变量接收@Observed装饰的class的实例,应用于观察多层嵌套场景,和父组件的数据源构建双向同步。

说明 仅@Observed/@ObjectLink可以观察嵌套场景,其他的状态变量仅能观察第一层,详情见各个装饰器章节的“观察变化和行为表现”小节。

管理应用拥有的状态,即图中Application级别的状态管理:

  • AppStorage是应用程序中的一个特殊的单例LocalStorage对象,是应用级的数据库,和进程绑定,通过@StorageProp和@StorageLink装饰器可以和组件联动。
  • AppStorage是应用状态的“中枢”,需要和组件(UI)交互的数据存入AppStorage,比如持久化数据PersistentStorage和环境变量Environment。UI再通过AppStorage提供的装饰器或者API接口,访问这些数据;
  • 框架还提供了LocalStorage,AppStorage是LocalStorage特殊的单例。LocalStorage是应用程序声明的应用状态的内存“数据库”,通常用于页面级的状态共享,@LocalStorageProp和@LocalStorageLink装饰器可以和UI联动。
其他状态管理功能

@Watch用于监听状态变量的变化。

$$运算符:给内置组件提供TS变量的引用,使得TS变量和内置组件的内部状态保持同步。

管理组件拥有的状态

@State装饰器:组件内状态

@State装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI会发生对应的渲染改变。

在状态变量相关装饰器中,@State是最基础的,使变量拥有状态属性的装饰器,它也是大部分状态变量的数据源。

概述

@State装饰的变量,与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问,在声明时必须指定其类型和本地初始化。初始化也可选择使用命名参数机制从父组件完成初始化。

@State装饰的变量拥有以下特点:

  • @State装饰的变量与子组件中的@Prop、@Link或@ObjectLink装饰变量之间建立单向或双向数据同步。
  • @State装饰的变量生命周期与其所属自定义组件的生命周期相同。
装饰器使用规则说明

@State变量装饰器

说明

装饰器参数

无

同步类型

不与父组件中任何类型的变量同步。

允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。 类型必须被指定。 不支持any,不支持简单类型和复杂类型的联合类型,不允许使用undefined和null。 说明 建议不要装饰Date类型,应用可能会产生异常行为。 不支持Length、ResourceStr、ResourceColor类型,Length、ResourceStr、ResourceColor为简单类型和复杂类型的联合类型。

被装饰变量的初始值

必须指定。

变量的传递/访问规则说明

传递/访问

说明

从父组件初始化

可选,从父组件初始化或者本地初始化。 支持父组件中常规变量、@State、@Link、@Prop、@Provide、@Consume、@ObjectLink、@StorageLink、@StorageProp、@LocalStorageLink和@LocalStorageProp装饰的变量,初始化子组件的@State。

用于初始化子组件

@State装饰的变量支持初始化子组件的常规变量、@State、@Link、@Prop、@Provide。

是否支持组件外访问

不支持,只能在组件内访问。

图1 初始化规则图示

观察变化和行为表现

并不是状态变量的所有更改都会引起UI的刷新,只有可以被框架观察到的修改才会引起UI刷新。该小节去介绍什么样的修改才能被观察到,以及观察到变化后,框架的是怎么引起UI刷新的,即框架的行为表现是什么。

观察变化
  • 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。
  1. // for simple type
  2. @State count: number = 0;
  3. // value changing can be observed
  4. this.count = 1;

复制

  • 当装饰的数据类型为class或者Object时,可以观察到自身的赋值的变化,和其属性赋值的变化,即Object.keys(observedObject)返回的所有属性。例子如下。

声明ClassA和Model类。

  1. class ClassA {
  2. public value: string;
  3. constructor(value: string) {
  4. this.value = value;
  5. }
  6. }
  7. class Model {
  8. public value: string;
  9. public name: ClassA;
  10. constructor(value: string, a: ClassA) {
  11. this.value = value;
  12. this.name = a;
  13. }
  14. }

复制

@State装饰的类型是Model

  1. // class类型
  2. @State title: Model = new Model('Hello', new ClassA('World'));

复制

对@State装饰变量的赋值。

  1. // class类型赋值
  2. this.title = new Model('Hi', new ClassA('ArkUI'));

复制

对@State装饰变量的属性赋值。

  1. // class属性的赋值
  2. this.title.value = 'Hi'

复制

嵌套属性的赋值观察不到。

  1. // 嵌套的属性赋值观察不到
  2. this.title.name.value = 'ArkUI'

复制

  • 当装饰的对象是array时,可以观察到数组本身的赋值和添加、删除、更新数组的变化。例子如下。

声明ClassA和Model类。

  1. class Model {
  2. public value: number;
  3. constructor(value: number) {
  4. this.value = value;
  5. }
  6. }

复制

@State装饰的对象为Model类型数组时。

@State title: Model[] = [new Model(11), new Model(1)]

复制

数组自身的赋值可以观察到。

this.title = [new Model(2)]

复制

数组项的赋值可以观察到。

this.title[0] = new Model(2)

复制

删除数组项可以观察到。

this.title.pop()

复制

新增数组项可以观察到。

this.title.push(new Model(12))

复制

框架行为
  • 当状态变量被改变时,查询依赖该状态变量的组件;
  • 执行依赖该状态变量的组件的更新方法,组件更新渲染;
  • 和该状态变量不相关的组件或者UI描述不会发生重新渲染,从而实现页面渲染的按需更新。
使用场景
装饰简单类型的变量

以下示例为@State装饰的简单类型,count被@State装饰成为状态变量,count的改变引起Button组件的刷新:

  • 当状态变量count改变时,查询到只有Button组件关联了它;
  • 执行Button组件的更新方法,实现按需刷新。
  1. @Entry
  2. @Component
  3. struct MyComponent {
  4. @State count: number = 0;
  5. build() {
  6. Button(`click times: ${this.count}`)
  7. .onClick(() => {
  8. this.count += 1;
  9. })
  10. }
  11. }

复制

装饰class对象类型的变量
  • 自定义组件MyComponent定义了被@State装饰的状态变量count和title,其中title的类型为自定义类Model。如果count或title的值发生变化,则查询MyComponent中使用该状态变量的UI组件,并进行重新渲染。
  • EntryComponent中有多个MyComponent组件实例,第一个MyComponent内部状态的更改不会影响第二个MyComponent。
  1. class Model {
  2. public value: string;
  3. constructor(value: string) {
  4. this.value = value;
  5. }
  6. }
  7. @Entry
  8. @Component
  9. struct EntryComponent {
  10. build() {
  11. Column() {
  12. // 此处指定的参数都将在初始渲染时覆盖本地定义的默认值,并不是所有的参数都需要从父组件初始化
  13. MyComponent({ count: 1, increaseBy: 2 })
  14. MyComponent({ title: new Model('Hello, World 2'), count: 7 })
  15. }
  16. }
  17. }
  18. @Component
  19. struct MyComponent {
  20. @State title: Model = new Model('Hello World');
  21. @State count: number = 0;
  22. private increaseBy: number = 1;
  23. build() {
  24. Column() {
  25. Text(`${this.title.value}`)
  26. Button(`Click to change title`).onClick(() => {
  27. // @State变量的更新将触发上面的Text组件内容更新
  28. this.title.value = this.title.value === 'Hello ArkUI' ? 'Hello World' : 'Hello ArkUI';
  29. })
  30. Button(`Click to increase count=${this.count}`).onClick(() => {
  31. // @State变量的更新将触发该Button组件的内容更新
  32. this.count += this.increaseBy;
  33. })
  34. }
  35. }
  36. }

复制

从该示例中,我们可以了解到@State变量首次渲染的初始化流程:

  • 使用默认的本地初始化:
  1. @State title: Model = new Model('Hello World');
  2. @State count: number = 0;

复制

  • 对于@State来说,命名参数机制传递的值并不是必选的,如果没有命名参数传值,则使用本地初始化的默认值
MyComponent({ count: 1, increaseBy: 2 })

最后,为了能让大家更好的去学习提升鸿蒙 (Harmony OS) 开发技术,小编连夜整理了一份30个G纯血版学习资料(含视频、电子书、学习文档等)以及一份在Github上持续爆火霸榜的《纯血版华为鸿蒙 (Harmony OS)开发手册》(共计890页),希望对大家有所帮助。

纯血版鸿蒙 HarmonyOS 4.0 视频学习资料

 需要以上视频学习资料小伙伴

请点击→纯血版全套鸿蒙HarmonyOS学习资料


《纯血版华为鸿蒙 (Harmony OS)开发手册》

这份手册涵盖了当前鸿蒙 (Harmony OS) 开发技术必掌握的核心知识点

纯血版鸿蒙 (Harmony OS)开发手册部分精彩内容

HarmonyOS 概念:

  • 系统定义
  • 技术架构
  • 技术特性
  • 系统安全

如何快速入门?

  • 基本概念
  • 构建第一个ArkTS应用
  • 构建第一个JS应用
  • ……


开发基础知识: 

  • 应用基础知识
  • 配置文件
  • 应用数据管理
  • 应用安全管理
  • 应用隐私保护
  • 三方应用调用管控机制
  • 资源分类与访问
  • 学习ArkTS语言
  • ……

基于ArkTS 开发:

  • Ability开发
  • UI开发
  • 公共事件与通知
  • 窗口管理
  • 媒体
  • 安全
  • 网络与链接
  • 电话服务
  • 数据管理
  • 后台任务(Background Task)管理
  • 设备管理
  • 设备使用信息统计
  • DFX
  • 国际化开发
  • 折叠屏系列
  • .……

获取以上文中提到的这份纯血版鸿蒙 (Harmony OS) 开发资料的小伙伴 

请点击→纯血版全套鸿蒙HarmonyOS学习资料


?写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing?,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新VIP学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

注:本文转载自blog.csdn.net的蜀道山QAQ的文章"https://blog.csdn.net/shudaoshanQAQ/article/details/135612222"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top