深入解析鸿蒙 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 |
---|---|
Array | push, pop, shift, unshift, splice, copyWithin, fill, reverse, sort |
Date | setFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds |
Map | set, clear, delete |
Set | add, clear, delete |