【鸿蒙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;
    }
}
相关推荐
青い月の魔女13 分钟前
数据结构初阶---二叉树
c语言·数据结构·笔记·学习·算法
qq_5895681020 分钟前
node.js web框架koa的使用
笔记·信息可视化·echarts
stm 学习ing1 小时前
HDLBits训练6
经验分享·笔记·fpga开发·fpga·eda·verilog hdl·vhdl
stm 学习ing2 小时前
HDLBits训练4
经验分享·笔记·fpga开发·课程设计·fpga·eda·verilog hdl
yg_小小程序员2 小时前
鸿蒙开发(16)使用DevEco Studio上的Git工具进行多远程仓管理
git·华为·harmonyos
炸毛的飞鼠2 小时前
汇编语言学习
笔记·学习
JasonYin~2 小时前
HarmonyOS NEXT 实战之元服务:静态案例效果---每日玩机技巧
harmonyos
轻口味2 小时前
【每日学点鸿蒙知识】多线程限制、axios组件下载进度问题、lpx问题、Web组件全局代理、ArrayList问题
华为·harmonyos
yuanlaile2 小时前
纯Dart Flutter库适配HarmonyOS
flutter·华为·harmonyos·flutter开发鸿蒙·harmonyos教程
yuanlaile2 小时前
Flutter开发HarmonyOS 鸿蒙App的好处、能力以及把Flutter项目打包成鸿蒙应用
flutter·华为·harmonyos·flutter开发鸿蒙