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%')
  }
}
相关推荐
奋斗的小青年!!30 分钟前
Flutter跨平台开发鸿蒙应用实战:OA系统考勤打卡组件深度解析
flutter·harmonyos·鸿蒙
全栈开发圈1 小时前
新书速览|鸿蒙之光HarmonyOS 6应用开发入门
华为·harmonyos
儿歌八万首3 小时前
鸿蒙 ArkUI 实战:沉浸式状态栏的 3 种实现方案
华为·harmonyos
大雷神3 小时前
HarmonyOS中考试模板开发教程
华为·harmonyos
全栈开发圈3 小时前
干货分享|鸿蒙6开发实战指南
人工智能·harmonyos·鸿蒙·鸿蒙系统
鸣弦artha4 小时前
Flutter框架跨平台鸿蒙开发 —— Image Widget 基础:图片加载方式
flutter·华为·harmonyos
奋斗的小青年!!5 小时前
在OpenHarmony上玩转Flutter弹出菜单:我的实战经验分享
flutter·harmonyos·鸿蒙
lili-felicity6 小时前
React Native for OpenHarmony 实战:加载效果的实现详解
javascript·react native·react.js·harmonyos
哈哈你是真的厉害6 小时前
React Native 鸿蒙跨平台开发:BaseConverter 进制转换
react native·react.js·harmonyos
奋斗的小青年!!6 小时前
Flutter跨平台开发:笔记分享功能适配OpenHarmony
flutter·harmonyos·鸿蒙