ArkTS的状态管理机制(State)

news/2024/6/1 22:47:23 标签: 前端, harmonyos, typescript, ArkTS, ArkUI

什么是ArkTS的状态管理机制 

声明式UI中,是以状态(State)来驱动视图更新的(View)。

状态是指驱动视图更新的数据(被装饰器标记的变量)。

视图是指UI描述渲染得到的用户页面。

互动事件可以改变状态的值。状态改变以后,又会触发事件,渲染页面。

这就形成了ArkTS的状态管理机制。

ArkTS的装饰器

ArkTS中的状态管理分为很多种不同的装饰器,他们有多种不一样的作用

@state 、 @Prop、 @Link 、@Provide 、 @Consume 、 @Observed 、 @ObjectLink

State装饰器

注意:

  1. @State装饰器标记的变量必须初始化,不能为空值
  2. @State装饰器支持Object、class、string、number、boolean、enum等类型以及这些类型的数据,不可以any、union等复杂类型。
  3. 嵌套类型以及数组中的对象无法触发视图更新。

案例 HelloWorld

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            this.message = 'Hello ArkTS'
          })
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
    }

  }
}

我们将@State去掉 就不能产生这个效果。 因为普通变量不能触发状态的渲染。

验证@State装饰器的作用

1.@State装饰器必须初始化

我们发现State装饰器没有初始值会报错。所以State装饰器必须要有初始值。

2.@State装饰器的支持类型

1.基本类型

 我们前面使用的是基本类型string,证明@State是支持基本类型的。

2.对象类型

我们定义一个类,@State使用对象类型来做声明。 


class Person{
  name:string
  age:number

  constructor(name:string,age:number) {
    this.name = name
    this.age = age
  }
}

@Entry
@Component
struct StatePage {
  @State p:Person = new Person('zhangsan',21)
  build() {
    Row() {
      Column() {
        Text(`${this.p.name} : ${this.p.age}`)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            this.p.age++
          })
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
    }

  }
}

我们会发现对象类型也可以动态的修改状态。

3.嵌套类型

嵌套类型中的属性改变不会触发视图的更新。


class Person{
  name:string
  age:number
  gf: Person

  constructor(name:string,age:number,gf?: Person) {
    this.name = name
    this.age = age
    this.gf = gf
  }
}

@Entry
@Component
struct StatePage {
  @State p:Person = new Person('zhangsan',21,new Person('LiSi',19))
  build() {
    Row() {
      Column() {
        Text(`${this.p.name} : ${this.p.age}`)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            this.p.age++
          })
        Text(`${this.p.gf.name} : ${this.p.gf.age}`)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            this.p.gf.age++
          })
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
    }

  }
}

我们会发现使用嵌套类型的时候,嵌套的对象不可以触发视图的更新。但其实值是加上的,在点击对象类型的时候,触发了渲染。 

4.数组

当@State声明的类型是一个数组的时候,数组的增添会触发视图的渲染,但是数组中如果存在对象,对象内的属性的更改不会触发渲染。


class Person{
  name:string
  age:number
  gf: Person

  constructor(name:string,age:number,gf?: Person) {
    this.name = name
    this.age = age
    this.gf = gf
  }
}

@Entry
@Component
struct StatePage {
  idx: number = 1
  @State p:Person = new Person('zhangsan',21,new Person('LiSi',19))
  @State gfs: Person[] = [
    new Person('WangWu',18),
    new Person('LaoLiu',78)
  ]
  build() {
    Row() {
      Column() {
        Text(`${this.p.name} : ${this.p.age}`)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            this.p.age++
          })
        Button('添加女友')
          .onClick(() => {
            this.gfs.push(new Person(`女友` + this.idx++,20))
          })
       Text('=女友列表=')
         .fontSize(50)
         .fontWeight(FontWeight.Bold)
        ForEach(
          this.gfs,
          (item,index) => {
            Row(){
              Text(`${item.name} : ${item.age}`)
                .fontSize(30)
                .onClick(()=>{
                  item.age++
                })
              Button("删除")
                .onClick(() => {
                  this.gfs.splice(index,1)
                })
            }
            .width('100%')
            .justifyContent(FlexAlign.SpaceAround)

          }
        )
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
    }

  }
}

我们会发现,增添和删除是可以触发页面的刷新呢,但是,数组中的对象的更改不会触发页面的渲染。


http://www.niftyadmin.cn/n/5261497.html

相关文章

CentOS 7 部署frp穿透内网

本文将介绍如何在CentOS 7.9上部署frp,并通过示例展示如何配置和测试内网穿透。 文章目录 (1)引言(2)准备工作(4)frps服务器端配置(5)frpc客户端配置(6&#…

使用 Timm 库替换 RT-DETR 主干网络 | 1000+ 主干融合RT-DETR

文章目录 前言版本差异说明替换方法parse_moedl( ) 方法_predict_once( ) 方法修改 yaml ,加载主干论文引用timm 是一个包含最先进计算机视觉模型、层、工具、优化器、调度器、数据加载器、数据增强和训练/评估脚本的库。 该库内置了 700 多个预训练模型,并且设计灵活易用。…

Android13适配所有文件管理权限

Android13适配所有文件管理权限 前言: 很早之前在Android11上面就适配过所有文件管理权限,这次是海外版升级到Android13,由于选择相册用的是第三方库,组内的同事没有上架Google的经验直接就提交代码,虽然功能没有问题…

[论文精读] 使用扩散模型生成真实感视频 - 【李飞飞团队新作,文生视频 新基准】

论文导读: 论文背景:2023年12月11日,AI科学家李飞飞团队与谷歌合作,推出了视频生成模型W.A.L.T(Window Attention Latent Transformer)——一个在共享潜在空间中训练图像和视频生成的、基于Transformer架构的扩散模型。李飞飞是华…

缓存穿透问题与解决方案

目录 引言 1. 缓存穿透的原因 1.1 不存在的数据请求 1.2 缓存键设计不当 2. 缓存穿透的影响 2.1 后端系统负载过重 2.2 数据库压力增大 2.3 用户体验降低 3. 解决缓存穿透的方案 3.1 布隆过滤器 3.2 缓存空对象 3.3 热点数据预加载 3.4 异步更新缓存 3.5 缓存击穿…

解决pytorch训练的过程中内存一直增加的问题

来自:解决pytorch训练的过程中内存一直增加的问题 - 知乎 pytorch训练中内存一直增加的原因(部分) 代码中存在累加loss,但每步的loss没加item() import torch import torch.nn as nn from collections import defaultdictif torch.cuda.is_available()…

【人工智能Ⅰ】实验8:DBSCAN聚类实验

实验8 DBSCAN聚类实验 一、实验目的 学习DBSCAN算法基本原理,掌握算法针对不同形式数据如何进行模型输入,并结合可视化工具对最终聚类结果开展分析。 二、实验内容 1:使用DBSCAN算法对iris数据集进行聚类算法应用。 2:使用DBS…

算法笔记—二分搜索

二分搜索 1. 有序数组中确定 num 存在还是不存在2. 有序数组找大于等于 num 的最左位置3. 有序数组找小于等于 num 的最右位置4. 二分搜索不一定发生在有序数组上 如果数组长度为n,二分搜索搜索次数是log2n次,时间复杂度O(log n) 1. 有序数组中确定 num …