HarmonyOS 状态管理 v2

状态管理更新到 v2 版本,使用 @ComponentV2 装饰自定义组件,在 @ComponentV2 版本中仅能使用 @Local、@Param、@Once、@Event、@Provider、@Consumer 等装饰器。

@Local

@Local 状态变量表示组件内部的状态, 必须在组件内部初始化, 不允许从外部初始化。

  • @Local装饰器只能在@ComponentV2装饰的自定义组件中使用。
  • @Local 仅能观察到状态变量的整体赋值,对于类对象类型的状态变量,无法直接观察到对类成员属性赋值的变化,需要结合 @ObservedV2和 @Trace
typescript 复制代码
@Entry
@ComponentV2
struct LocalPage {
  @Local skill: string = 'Android';
  @Local user: LocalUser = new LocalUser('Android')
  @Local observedUser: ObservedLocalUser = new ObservedLocalUser('Android')

  build() {
    Column() {
      Text('message: ' + this.skill)
      Text('user.skill: ' + this.user.skill)
      Text('observedUser.skill: ' + this.observedUser.skill)

      Button('change').onClick((event: ClickEvent) => {
        this.skill = 'Kotlin'                                // 有效刷新,可以观察到状态变量的整体赋值,
        this.user = new LocalUser('Kotlin')                  // 有效刷新,可以观察到状态变量的整体赋值,
        this.observedUser = new ObservedLocalUser('Kotlin')  // 有效刷新,可以观察到状态变量的整体赋值,
      })
      Button('change property').onClick((event: ClickEvent) => {
        this.user.skill = 'ArkUI' // 无效刷新,@Local无法直接观察到状态变量深层属性的变化,需要结合 @ObservedV2,@Trace
        this.observedUser.skill = 'ArkUI' // 有效刷新,结合 @ObservedV2,@Trace
      })

    }
    .height('100%')
    .width('100%')
  }
}

export class LocalUser {
  skill: string

  constructor(skill: string) {
    this.skill = skill;
  }
}

@ObservedV2
export class ObservedLocalUser {
  @Trace skill: string

  constructor(skill: string) {
    this.skill = skill;
  }
}

@Param

@Param表示组件从外部传入的状态,使得父子组件之间的数据能够进行同步.

  • @Param装饰的变量支持本地初始化,但是不允许在组件内部直接修改变量本身。
  • 被@Param装饰的变量能够在初始化自定义组件时从外部传入,当数据源也是状态变量时,数据源的修改会同步给@Param。
  • 对于复杂类型如类对象,@Param会接受数据源的引用。在组件内可以修改类对象中的属性,该修改会同步到数据源。
typescript 复制代码
@Entry
@ComponentV2
struct ParamPage {
  @Local message: string = 'Hello World';
  @Local user: User = new User('Android', 15)

  build() {
    Column({ space: 6 }) {
      Text(this.message).onClick(() => this.message = 'parent set')
      Text(this.user.name + " -- " + this.user.age).onClick(() => this.user = new User('parent', 12))

      Button('change').onClick((event: ClickEvent) => {
        this.message = 'harmony' // 有效刷新,可以观察到状态变量的修改
        this.user = new User('harmony', 12) // 有效刷新, 可以观察到状态变量的整体赋值
      })
      Button('change property').onClick((event: ClickEvent) => {
        this.user.name = 'arkui' // 有效刷新,因为结合了 @ObservedV2 和 @Trace
      })
      Blank().height(10)
      ChildParam({ msg: this.message, user: this.user })

    }
    .height('100%')
    .width('100%')
  }
}

@ComponentV2
struct ChildParam {
  @Param msg: string = 'child init'
  @Param user: User = new User('child init', 1)

  build() {
    Column() {
      Text(this.msg).fontSize(20).onClick(() => {
        // this.msg = 'compose'   // 报错,不允许修改 @Param 状态变量,若需要修改@Param变量,需要结合 @Event
      })
      Text(this.user.name + " - " + this.user.age).fontSize(20).onClick(() => {
        // this.user = new User('',12)   //  报错,不允许修改 @Param 状态变量
        this.user.name = 'Compose' // 可以修改 @Param 状态变量的属性,修改可以同步给父组件
      })
    }
  }
}

@ObservedV2
class User {
  @Trace name: string
  age: number

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

@Event

由于@Param装饰的变量在本地无法更改,使用@Event装饰器装饰回调方法并调用,可以实现更改数据源的变量,再通过@Local的同步机制,将修改同步回@Param,以此达到主动更新@Param装饰变量的效果

  • @Event装饰的回调方法中参数以及返回值由自己任意定义。
  • 当@Event未被外部初始化,但本地有默认值时,会使用本地默认的函数进行处理
less 复制代码
@Entry
@ComponentV2
struct EventPage {
  @Local message: string = 'Hello World';
  @Local user: EventUser = new EventUser('Kotlin')

  build() {
    Column() {
      Text(this.message)
      Text(this.user.name)
      Button('change').onClick((event: ClickEvent) => {
        this.message = 'Hello HarmonyOS'
        this.user = new EventUser('ArkTS')
      })
      Button('change property').onClick((event: ClickEvent) => {
        this.user.name = 'arkUI'
      })
      ChildEvent({
        msg: this.message,
        user: this.user,
        onMsgChange: (msg) => {
          this.message = msg
        },
        onUserChange: (user) => {
          this.user = user
        }
      })
    }
    .height('100%')
    .width('100%')
  }
}

@ComponentV2
struct ChildEvent {
  @Param msg: string = ''
  @Param user: EventUser = new EventUser('')
  @Event onMsgChange: (msg: string) => void = () => {
  }
  @Event onUserChange: (user: EventUser) => void = () => {
  }

  build() {
    Column() {
      Text(this.msg).fontSize(20).onClick(() => {
        this.onMsgChange('child set')
      })
      Text(this.user.name).onClick(() => {
        this.onUserChange(new EventUser('child user'))
      })
    }
  }
}

class EventUser {
  name: string

  constructor(name: string) {
    this.name = name
  }
}

@Once

@Once装饰器仅在变量初始化时接受外部传入值进行初始化,当后续数据源更改时,不会将修改同步给子组件:

  • @Once必须搭配@Param装饰器使用,单独使用或搭配其他装饰器使用都是不允许的。
  • @Once不影响@Param的观测能力,仅针对数据源的变化做拦截。
typescript 复制代码
@Entry
@ComponentV2
struct OncePage {
  @Local message: string = 'Hello World';

  build() {
    Column() {
      Text(this.message).onClick(() => this.message = 'parent')
      ChildOnce({ msg: this.message })
    }
    .height('100%')
    .width('100%')
  }
}


@ComponentV2
struct ChildOnce {
  @Once @Param msg: string = ''

  build() {
    Text(this.msg)
  }
}

@Monitor

@Monitor 和 @Watch 类似,都是用于监听变量的变化, 当监听的变量变化时会触发对应的回调函数

typescript 复制代码
import { promptAction } from '@kit.ArkUI';
import { User } from '../../models/User';

@Entry
@ComponentV2
struct MonitorPage {
  @Local message: string = 'Hello World';
  @Local user: User = new User('Android', 12)

  @Monitor('message', 'user.name')
  onChange() {
    promptAction.showToast({ message: 'onChange: ' + this.message })
    promptAction.showToast({ message: 'user.name: ' + this.user.name })
  }

  build() {
    Column() {
      Text(this.message).fontSize(30).onClick(() => this.message = 'android')
      Text(this.user.name + '-' + this.user.age).onClick(()=> this.user.name = 'new name')

    }
    .height('100%')
    .width('100%')
  }
}
相关推荐
长弓三石11 小时前
鸿蒙网络编程系列50-仓颉版TCP回声服务器示例
网络·tcp/ip·harmonyos
hhg13 小时前
【harmonyOS】启动框架----优化启动速度和分离初始化代码
harmonyos
帅比九日17 小时前
【HarmonyOS NEXT】深入解析HarmonyOS NEXT中的媒体处理功能
华为·harmonyos·harmonyos next
zhongcx0119 小时前
鸿蒙NEXT开发案例:文字转拼音
华为·harmonyos·鸿蒙·鸿蒙next
yuwinter1 天前
鸿蒙HarmonyOS学习笔记(1)
学习·华为·harmonyos
爱笑的眼睛112 天前
鸿蒙面试题-某迈-2024年11月22日
华为·harmonyos
拾荒李2 天前
鸿蒙开发-音视频
华为·音视频·harmonyos
二流小码农2 天前
鸿蒙开发:自定义一个任意位置弹出的Dialog
android·ios·harmonyos
zhongcx012 天前
鸿蒙NEXT开发案例:二维码的生成与识别
华为·harmonyos·鸿蒙·鸿蒙next
清晨人儿2 天前
鸿蒙主流路由详解
华为·harmonyos