【鸿蒙HarmonyOS开发笔记】深入状态管理,详解@ObjectLink 和 @Observed装饰器

前言

前篇回顾:【鸿蒙HarmonyOS开发笔记】状态管理入门

在之前的文章中我们简单了解了ArkTS 提供了一系列状态相关的装饰器,例如@State@Prop@Link@Provide@Consume等等。

本文我们继续记录各种状态器所能观察到的变化范围


@State

允许装饰的类型

@State允许装饰的变量类型有string、number、boolean、object、classenum类型,以及这些类型的数组

框架能够观察到的变化

并不是@State状态变量的所有更改都会引起UI的刷新,只有可以被框架观察到的修改才会引起UI刷新。能被框架观察到的变化如下

boolean、string、number类型

当@State装饰的变量类型为boolean、string、number类型时,可以观察到赋值的变化

例如

typescript 复制代码
//状态变量定义
@State count:number = 1; 

//状态变量操作
this.count++; //可以观察到

class、object类型

注意:当@State装饰的变量类型为class或者object时,可以观察到变量自身赋值的变化,和其属性赋值的变化。需要注意的是,若某个属性也为class或者 object,则嵌套属性的变化是观察不到的。

例如

typescript 复制代码
//类型定义
class Employee {
    name: string;
    age: number;
    job: Job;

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

class Job {
    name: string;
    salary: number;

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

//状态定义
@State employee: Employee = new Employee('张三', 28, new Job('销售', 8000))

//状态操作
employee = new Employee('李四', 26, new Job('行政', 6000))//状态变量重新赋值,可以观察到

employee.age++;//修改状态变量的属性,可以观察到

employee.job.salary++;//修改状态变量的属性的属性,不可以观察到

数组类型

@State装饰的变量类型为数组时,可以观察到数组本身赋值的变化,和其元素的添加、删除及更新的变化,若元素类型为 class 或者 object 时,元素属性的变化,是观察不到的。

例如

typescript 复制代码
//类型定义
export class Person {
    name: string;
    age: number;

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



//状态定义
@State persons: Person[] = [new Person('张三', 19), new Person('李四', 20)];

//状态操作
persons = [];//状态变量重新赋值,可以观察到

persons.push(new Person('王五',21));//新增数组元素,可以观察到

persons[0]=new Person('张三',22);//对数组元素重新赋值,可以观察到

persons[1].age++;//修改数组元素的属性,不可以观察到

总结

对于classobject和数组类型,框架仅能观察到@State变量第一层属性的变化,例如employee.age++persons[0]=new Person('张三',22),但第二层属性的变化是观察不到的,例如employee.job.salary++persons[1].age++


@Prop

允许装饰的类型

@Prop允许装饰的变量类型有string、number、boolean、enum,注意不支持class、object数组

框架能够观察到的变化

当装饰的类型是允许的类型,即string、number、boolean、enum类型时,所有赋值的变化都可以观察到。


允许装饰的类型(同@State

@Link允许装饰的变量类型有string、number、boolean、object、classenum类型,以及这些类型的数组

框架能够观察到的变化(同@State

● 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。

● 当装饰的数据类型为class或者object时,可以观察到变量自身赋值的变化,和其属性赋值的变化。需要注意的是,若某个属性也为 class 或者 object,则嵌套属性的变化是观察不到的。

● 当装饰的数据类型为数组时,可以可以观察到数组本身赋值的变化,和其元素的添加、删除及更新的变化,若元素类型为 class 或者object时,元素属性的变化,是观察不到的。


@Provide @Consume

允许装饰的类型(同@State

@Provide@Consume允许装饰的变量类型有string、number、boolean、object、classenum类型,以及这些类型的数组。

框架能够观察到的变化(同@State

● 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化

● 当装饰的数据类型为class或者object时,可以观察到变量自身赋值的变化,和其属性赋值的变化。需要注意的是,若某个属性也为 class 或者 object,则嵌套属性的变化是观察不到的。

● 当装饰的数据类型为数组时,可以可以观察到数组本身赋值的变化,和其元素的添加、删除及更新的变化,若元素类型为 class 或者 object 时,元素属性的变化,是观察不到的。


总结

前文所述的装饰器都仅能观察到状态变量第一层的变化,而第二层的变化是观察不到的。如需观察到这些状态变量第二层的变化,则需要用到 ·@ObjectLink·和·@Observed·装饰器。


示例代码

typescript 复制代码
import { Employee, Job } from './model/DataModel'

@Entry
@Component
struct EmployeeInfo {
  @State employee: Employee = new Employee('张三', 28, new Job('销售', 8000))

  build() {
    Column() {
      Column({ space: 20 }) {
        Row({ space: 20 }) {
          Text('姓名').textStyle()
          Text(this.employee.name).textStyle()
        }

        Row({ space: 20 }) {
          Text('年龄').textStyle()
          Counter() {
            Text(this.employee.age.toString()).textStyle()
          }
          .onInc(() => {
            this.employee.age++;
          })
          .onDec(() => {
            this.employee.age--;
          })
        }

        Row({ space: 20 }) {
          Text('岗位').textStyle()
          JobInfo({ job: this.employee.job })
        }

      }
      .width('100%')
      .backgroundColor(Color.White)
      .borderRadius(10)
      .alignItems(HorizontalAlign.Start)
      .padding(20)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#E9E9EA')
    .padding(10)
    .justifyContent(FlexAlign.Center)
  }
}


@Component
struct JobInfo {
  @ObjectLink job: Job

  build() {
    Column({ space: 10 }) {
      Row({ space: 20 }) {
        Text('名称').textStyle()
        Text(this.job.name).textStyle()
      }

      Row({ space: 20 }) {
        Text('薪资').textStyle()
        Counter() {
          Text(this.job.salary.toString()).textStyle()
        }
        .width(140)
        .onInc(() => {
          this.job.salary++;
        })
        .onDec(() => {
          this.job.salary--;
        })
      }
    }
    .backgroundColor('#CCE3CB')
    .padding(20)
    .borderRadius(10)
    .alignItems(HorizontalAlign.Start)
  }
}


@Extend(Text) function textStyle() {
  .fontSize(20)
  .fontWeight(FontWeight.Medium)
}

DataModel

typescript 复制代码
export class Employee {
    name: string;
    age: number;
    job: Job;

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

@Observed
export class Job {
    name: string;
    salary: number;

    constructor(name: string, salary: number) {
        this.name = name;
        this.salary = salary;
    }
}
相关推荐
网络小白不怕黑41 分钟前
华为设备 QoS 流分类与流标记深度解析及实验脚本
网络·华为
网络小白不怕黑1 小时前
华为交换机堆叠与集群技术深度解析附带脚本
网络·华为
西岭千秋雪_1 小时前
Redis性能优化
数据库·redis·笔记·学习·缓存·性能优化
HuashuiMu花水木2 小时前
Matplotlib笔记4----------图像处理
图像处理·笔记·matplotlib
DES 仿真实践家3 小时前
【Day 11-N22】Python类(3)——Python的继承性、多继承、方法重写
开发语言·笔记·python
IMPYLH9 小时前
Python 的内置函数 reversed
笔记·python
幽蓝计划12 小时前
HarmonyOS NEXT仓颉开发语言实战案例:动态广场
华为·harmonyos
ysa05103013 小时前
数论基础知识和模板
数据结构·c++·笔记·算法
今天背单词了吗98013 小时前
算法学习笔记:7.Dijkstra 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·数据结构·笔记·算法
mitt_14 小时前
《人生顶层设计》读书笔记7
笔记