深入解析鸿蒙 ArkTS 中的 @Local 装饰器

目录

前言

1.什么是@Local

2.@Local的特点与优势

1.私有状态

2.响应式

3.与V2生命周期兼容

4.类型安全

3.详细用法

1. boolean、string、number

2. 类对象

3.单类型数组

4.嵌套类或对象数组

5.内置类型


前言

        在鸿蒙 ArkTS 开发中,组件的状态管理是核心能力之一。随着 ArkTS 0.8+ 版本的演进,V2 组件体系引入了新的状态管理装饰器,其中 @Local 是最常用的一种。本文将全面介绍 @Local 的作用、使用方法、优势及实际案例。

        这里需要说明的是:

从API version 12开始,在@ComponentV2装饰的自定义组件中支持使用@Local装饰器。

从API version 12开始,该装饰器支持在元服务中使用。

1.什么是@Local

        @Local 是 ArkTS V2 组件体系中用于声明组件内部私有状态的装饰器。它类似于V1的 @State,但在V2中功能更精细,性能更高。@Local 声明的状态只属于当前组件,外部无法直接访问或修改,保证了组件内部状态的封装性和独立性。 

        使用@Local 非常简单,你只需要在组件的类成员上加上装饰器即可:

@ComponentV2
struct CounterComponent {
  @Local count: number = 0; // 内部状态

  build() {
    Column() {
      Text(`当前计数:${this.count}`)
        .fontSize(24)
        .padding(20)
      Row() {
        Button('增加')
          .onClick(() => { this.count++ })
        Button('减少')
          .onClick(() => { this.count-- })
      }.justifyContent(FlexAlign.SpaceAround)
    }
  }
}

        在上面的代码中:

        @Local count: number = 0:定义组件的私有状态count,初始值为0。

        当count 发生变化时,组件会自动重新渲染。

        外部无法直接访问 count,保证状态的封装性。

2.@Local的特点与优势

1.私有状态

        @Local声明的状态仅属于当前组件,保证了组件内部的状态封装。其他组件或父组件无法直接访问或修改它。

2.响应式

        组件会自动监听@Local 修饰的状态,当状态发生变化时,组件会触发重新渲染,无需手动刷新。

3.与V2生命周期兼容

        @Local与V2组件的生命周期和性能优化机制兼容,支持冻结非活跃组件的状态监听,提高性能。

4.类型安全

        使用TypeScript 的类型系统,@Local 支持类型推导和静态检查,减少运行时错误。

3.详细用法

        使用@Local装饰的变量具有被观测变化的能力。当装饰的变量发生变化时,会触发该变量绑定的UI组件刷新。

1. boolean、string、number

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

@ComponentV2
struct TodoListComponent {
  @Local todos: string[] = []

  addTodo(todo: string) {
    this.todos = [...this.todos, todo]; // 替换式赋值,触发渲染
  }

  build() {
    Column() {
      ForEach(this.todos, (item, index) => {
        ListItem() {
          Text(item)
        }
      }, item => item)
      Button('添加任务').onClick(() => this.addTodo('新任务'))
    }
  }
}

2. 类对象

        当装饰的变量类型为类对象时,仅可以观察到对类对象整体赋值的变化,无法直接观察到对类成员属性赋值的变化,对类成员属性的观察依赖@ObservedV2@Trace装饰器。注意,API version 19之前,@Local无法和@Observed装饰的类实例对象混用。API version 19及以后,支持部分状态管理V1V2混用能力,允许@Local和@Observed同时使用,详情见状态管理V1V2混用文档

        如果我们定义了一个RawObject对象:

class RawObject {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}
@ObservedV2
class ObservedObject {
  @Trace name: string;
  constructor(name: string) {
    this.name = name;
  }
}

@Entry
@ComponentV2
struct LocalExample01 {

  @Local rawObject: RawObject = new RawObject("rawObject");
  @Local observedObject: ObservedObject = new ObservedObject("observedObject");

  build() {
    NavDestination(){
      Column() {
        Row(){
          Column(){
            Text(`${this.rawObject.name}`).margin({top:20})
            Text(`${this.observedObject.name}`).margin({top:20})
            Button("change object")
              .onClick(() => {
                // 对类对象整体的修改均能观察到
                this.rawObject = new RawObject("new rawObject");
                this.observedObject = new ObservedObject("new observedObject");
              }).margin({top:20})
            Button("change name")
              .onClick(() => {
                // @Local不具备观察类对象属性的能力,因此对rawObject.name的修改无法观察到
                this.rawObject.name = "new rawObject name";
                // 由于ObservedObject的name属性被@Trace装饰,因此对observedObject.name的修改能被观察到
                this.observedObject.name = "new observedObject name";
              }).margin({top:20})
          }.backgroundColor(Color.White).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).margin({top:20,bottom:20})
        }.margin({top:20,left:20,right:20}).borderColor(Color.Gray).width('100%').borderRadius(5).backgroundColor(Color.White).justifyContent(FlexAlign.Center)

      }
      .padding({
        left: '12vp',
        right: '12vp',
        bottom: '24vp'
      })
      .backgroundColor('#F1F3F5')
      .width('100%')
      .height('100%')
    }.title("Local修饰类对象")
  }
}

3.单类型数组

        当装饰简单类型数组时,可以观察到数组整体或数组项的变化。

        以下面的代码为例,点击按钮之后,UI中始终数组元素的Text实时刷新。

@Entry
@ComponentV2
struct LocalExample02 {
  @Local numArr: number[] = [1,2,3,4,5];  // 使用@Local装饰一维数组变量
  @Local dimensionTwo: number[][] = [[1,2,3],[4,5,6]]; // 使用@Local装饰二维数组变量

  build() {
    NavDestination(){
      Column() {
        Text(`${this.numArr[0]}`)
        Text(`${this.numArr[1]}`)
        Text(`${this.numArr[2]}`)
        Text(`${this.dimensionTwo[0][0]}`)
        Text(`${this.dimensionTwo[1][1]}`)
        Button("change array item") // 按钮1:修改数组中的特定元素
          .onClick(() => {
            this.numArr[0]++;
            this.numArr[1] += 2;
            this.dimensionTwo[0][0] = 0;
            this.dimensionTwo[1][1] = 0;
          })
        Button("change whole array") // 按钮2:替换整个数组
          .onClick(() => {
            this.numArr = [5,4,3,2,1];
            this.dimensionTwo = [[7,8,9],[0,1,2]];
          })
      }.justifyContent(FlexAlign.SpaceEvenly).width('100%').height('100%')
    }.title("简单的数组")
  }
}

4.嵌套类或对象数组

        当装饰的变量是嵌套类或对象数组时,@Local无法观察深层对象属性的变化。对深层对象属性的观测依赖@ObservedV2与@Trace装饰器。

5.内置类型

        当装饰内置类型时,可以观察到变量整体赋值及API调用带来的变化。

类型可观测变化的API
Arraypush, pop, shift, unshift, splice, copyWithin, fill, reverse, sort
DatesetFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds
Mapset, clear, delete
Setadd, clear, delete
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫柱子哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值