装饰器用法
在HarmonyOS应用开发中,状态管理是构建动态用户界面的重要部分。ArkUI框架提供了多种装饰器来管理状态变量,包括 @State、@Prop、@Link、@Provide、@Consume、@ObjectLink、@StorageProp、 等。下面将详细介绍这些装饰器的用法
1.@State 装饰器
@State 是HarmonyOS中最基本的状态管理装饰器,用于在组件内部声明一个状态变量。
@State装饰器标记的变量必须初始化,不能为空值;@State支持Object、class、string、number、boolean、enum类型以及这些类型的数组;嵌套类型以及数组中的对象属性无法触发视图更新
写法
@Entry
@Component
struct TestComponent {
@State count: number = 0;
build() {
Column() {
Text(this.count + '数字')
.width('90%')
Button('修改文本标题')
.width('90%')
.height('40')
.onClick(() => {
this.count += 1
})
}
.width('100%')
.height('100%')
}
}
特点
- 私有性:@State 装饰的变量是组件私有的,只能在组件内部访问。
- 自动更新: @State 装饰的变量改变会自动更新应用给变量的UI组件
- 生命周期: @State 的生命周期与所在组件相同
2.@Prop 装饰器
@Prop 用于创建父子组件的单向数据传递,并且修饰的变量无须初始化
写法
@Entry
@Component
struct TaskManagePage {
@State totalTask: number = 0
@State finishTask: number = 0
build() {
Column({space: 10}){
// 2.任务进度卡片
TaskStatistics({totalTask: this.totalTask, finishTask: this.finishTask})
}
.width('100%')
.height('100%')
.backgroundColor('#F1F2F3')
}
}
@Component
export default struct TaskStatistics {
@Prop totalTask: number = 0
@Prop finishTask: number = 0
build() {
Row() {
Text('任务进度: ')
.fontSize(30)
.fontWeight(FontWeight.Bold)
Stack() {
Progress({
value: this.finishTask,
total: this.totalTask,
type: ProgressType.Ring
})
.width(100)
Row() {
Text(this.finishTask.toString())
.fontSize(24)
.fontColor('#36D')
Text(' / ' + this.totalTask.toString())
.fontSize(24)
}
}
}
.card()
.margin({top: 5, bottom: 10})
.justifyContent(FlexAlign.SpaceEvenly)
}
}
特点
- 单向同步:父组件的状态变化会同步到子组件的 @Prop 变量,但子组件的 @Prop 变量的修改不会同步回父组件。
- 初始化: @Prop 变量可以在声明时不能初始化,也可以从父组件初始化
- 类型限制: @Prop 变量必须有明确的类型声明。
- 支持类型:只支持string、number、boolean、enum、class、数组、object类型
3. @Link 装饰器
@Link用于创建父子组件间的双向数据绑定
写法
@Entry
@Component
struct TaskManagePage {
@State totalTask: number = 0
@State finishTask: number = 0
build() {
Column({space: 10}){
TaskList({totalTask: $totalTask, finishTask:$finishTask})
}
.width('100%')
.height('100%')
.backgroundColor('#F1F2F3')
}
}
@Component
export default struct TaskList {
// 总任务数量
@Link totalTask: number
@Link finishTask: number
idx: number = 1
// 任务信息弹窗
dialogController: CustomDialogController = new CustomDialogController({
builder: TaskInfoDialog({onTaskConfirm: this.handleAddTask.bind(this)})
})
aboutToAppear(): void {
// 查询任务列表
console.log('TaskTag', '初始化组件, 查询任务列表')
TaskModel.getTaskList()
.then(tasks => {
this.tasks = tasks
// 更新任务状态
this.handleTaskChange()
})
}
handleTaskChange() {
// 1. 更新任务总数量
this.totalTask = this.tasks.length
// 2. 更新已完成任务数量
this.finishTask = this.tasks.filter(item => item.finished).length
}
handleAddTask(name: string) {
// 1. 新增任务
TaskModel.addTask(name)
.then(id => {
console.log('taskTag', '处理新增任务: ', name)
// 回显到数组页面
this.tasks.push(new TaskInfo(id,name))
// 2. 更新任务完成状态
this.handleTaskChange()
// 3. 关闭对话框
this.dialogController.close()
})
.catch((error: Error) => console.log('taskTag', '新增任务失败: ', name, JSON.stringify(error)))
}
// 任务数组
@State tasks: TaskInfo[] = []
build() {
Column() {
// 新增任务数组
Button('新增任务')
.width(200)
.margin({bottom: 10})
.onClick(()=> {
// 打开新增表单对话框
this.dialogController.open()
})
// 2. 任务列表
List({space: 10}){
ForEach(
this.tasks,
(item: TaskInfo, index) => {
ListItem() {
TaskItem({item: item, onTaskChange: this.handleTaskChange.bind(this)})
}
.swipeAction({end: this.DeleteButton(index, item.id)})
}
)
}
.width('100%')
.layoutWeight(1)
.alignListItem(ListItemAlign.Center)
}
}
}
特点:
- 双向同步:父组件和子组件的 @Link 变量之间可以相互影响,实现双向数据同步。
- 初始化:@Link 变量必须在声明时指定类型,不能初始化
- 数据绑定:@Link 变量与UI组件的数据绑定是双向的,这意味着UI组件的交互会直接影响 @Link 变量的值。
- 父子类型一致、string、number、boolean、enum、object、class,以及他们的数组
- 数组中元素增、删、替换会引起刷新
- 嵌套类型以及数组中的对象属性无法触及属性更新
4. @Provide 和 @Consume 装饰器
@Provide 和 @Consume 用于跨组件层级同步状态变量
写法
@Component
struct ProviderComponent {
@Provide('key') fontSize: number = 16 // ('key')可以不加不加的话 两个声明属性要一样
build() {
// UI构建逻辑
}
}
@Component
struct ConsumerComponent {
@Consume('key') fontSize: number // ('key')可以不加 不加的话 两个声明属性要一样
build() {
// UI构建逻辑
}
}
特点:
- 跨层级同步:@Provide 定义的状态变量可以在其子组件中通过 @Consume 使用,实现跨组件层级的数据同步。
- 灵活性:@Provide 和 @Consume 不局限于父子组件关系,可以用于任意层次的组件之间
5 @ObjkectLink 装饰器
@ObjectLink 用于观察和同步对象属性的变化。
写法
@Component
export default struct TaskItem {
@ObjectLink item: TaskInfo
@Prop onTaskChange: (item: TaskInfo) => void
build() {
Row() {
if (this.item.finished) {
Text(this.item.name)
.finishedTask()
}else {
Text(this.item.name)
}
Checkbox()
.select(this.item.finished)
.onChange( async val => {
// 1. 更新当前任务状态
TaskModel.updateTaskStatus(this.item.id, val)
?.then(() => {
this.item.finished = val
// 2.更新已完成任务数量
this.onTaskChange(this.item)
})
.catch((error:Error) => console.log('taskTag', '更新任务状态失败, id = ', this.item.id, JSON.stringify(error)))
})
}
.card()
.justifyContent(FlexAlign.SpaceBetween)
}
}
@Observed
export default class TaskInfo {
id: number = 0
// 任务名称
name: string = ''
// 任务状态 是否完成
finished: boolean = false
constructor(id: number, name: string) {
this.id = id
this.name = name
this.finished = false
}
}
特点:
- 属性同步:@ObjectLink 允许您观察和同步对象属性的变化。当对象属性发生变化时,UI会相应地更新。
- 初始化:@ObjectLink 变量必须在声明时指定对象类型和初始值。
- 深度观察:@ObjectLink 可以观察对象深层嵌套的属性变化。
6. @Extend 和 @Style
@Extend(Text) // 继承模式,只能写在全局内
@Extend(Text) function priceText() {
.fontColor('#F36D')
.fontSize(18)
}
@Style // 全局公共样式
@Styles function filleScreen() {
.width('100%')
.height('100%')
.backgroundColor('#EFEFEF')
.padding(20)
}
7. @StorageProp
@StorageProp 是一个装饰器,用于在组件内部变量与
AppStorage 中指定属性之间建立单向数据同步。当你使用
@StorageProp(key) 装饰一个组件内的变量时,这个变量就会与
AppStorage 中对应
key 的属性绑定。这意味着,如果
AppStorage 中给定
key 的属性发生改变,这个改变会被同步到
@StorageProp 装饰的变量中,并覆盖掉本地的修改。但是,本地对
@StorageProp 变量的修改不会同步回






网友评论