美文网首页
HarmonyOS 学习记录系列之装饰器写法

HarmonyOS 学习记录系列之装饰器写法

作者: 简单就是真 | 来源:发表于2025-07-05 21:29 被阅读0次

装饰器用法

在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%')
       }
}
特点
    1. 私有性:@State 装饰的变量是组件私有的,只能在组件内部访问。
    1. 自动更新: @State 装饰的变量改变会自动更新应用给变量的UI组件
    1. 生命周期: @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 变量的修改不会同步回

相关文章

  • React开发之【Mobx状态管理,非装饰器模式】

    React开发之【Mobx状态管理,非装饰器模式】 React项目装饰器开启失败, 下面是不用装饰器模式的写法 A...

  • [Decorator] 学习

    # Javascript 中的装饰器 # ES6 系列之我们来聊聊装饰器

  • 装饰器详解

    装饰器基本写法: 高级一点的装饰器 带参数的装饰器和类装饰器属于进阶的内容。在理解这些装饰器之前,最好对函数的闭包...

  • webpack实战之(手把手教你从0开始搭建一个vue项目)

    前言 我们前面从前端架构: 前端框架系列之(装饰器Decorator) 前端框架系列之(vue-class-com...

  • 2019-05-26python装饰器到底是什么?

    装饰器例子 参考语法 装饰器是什么?个人理解,装饰器,是python中一种写法的定义。他仍然符合python的基本...

  • 装饰器的写法

    摘要 装饰器是在不修改原来函数的情况下,对函数增新的功能的一种方法装饰器内可带参数一个函数可以有多个装饰器 实现方...

  • ts装饰器写法

    今天做项目的时候发现要用到watch来监听,所以就学习了watch的装饰器写法,然后顺便把之前用过的都看了,这里做...

  • 前端框架系列之(mvc)

    前言 前面我们写了三篇关于es装饰器的文章了,感兴趣的可以去看看: 前端框架系列之(装饰器Decorator) 前...

  • Python装饰器

    Python装饰器 一、函数装饰器 1.无参装饰器 示例:日志记录装饰器 2.带参装饰器 示例: 二、类装饰器 示例:

  • Python ☞ day 5

    Python学习笔记之 装饰器& 偏函数 & 异常处理 & 断言 & 文件读写 &编码与解码 装饰器 概念:是一个...

网友评论

      本文标题:HarmonyOS 学习记录系列之装饰器写法

      本文链接:https://www.haomeiwen.com/subject/erdagjtx.html