【鸿蒙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类型时,可以观察到赋值的变化

例如

//状态变量定义
@State count:number = 1; 

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

class、object类型

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

例如

//类型定义
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 时,元素属性的变化,是观察不到的。

例如

//类型定义
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类型时,所有赋值的变化都可以观察到。


@Link

允许装饰的类型(同@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·装饰器。


@ObjectLink @Observed

在这里插入图片描述

示例代码

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



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;
    }
}

最近更新

  1. TCP协议是安全的吗?

    2024-03-20 01:28:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-20 01:28:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-20 01:28:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-20 01:28:02       20 阅读

热门阅读

  1. vue回车键进行列表页查询

    2024-03-20 01:28:02       23 阅读
  2. 2024蓝桥杯每日一题(BFS)

    2024-03-20 01:28:02       21 阅读
  3. Streampark 入门到生产实践

    2024-03-20 01:28:02       18 阅读
  4. OpenJudge - 13:大整数的因子

    2024-03-20 01:28:02       19 阅读
  5. Chapter 1 - 3. Introduction to Congestion in Storage Networks

    2024-03-20 01:28:02       21 阅读
  6. 面试算法-45-分发糖果

    2024-03-20 01:28:02       23 阅读
  7. leetcode 139. 单词拆分

    2024-03-20 01:28:02       19 阅读
  8. 【Numpy】(2)numpy对象和random模块

    2024-03-20 01:28:02       20 阅读
  9. 如何在海外服务器上配置静态路由?

    2024-03-20 01:28:02       21 阅读
  10. YS/T 429.2-2012 有机聚合物喷涂幕墙铝单板检测

    2024-03-20 01:28:02       22 阅读