鸿蒙装饰器

Posted on By ᵇᵒ

鸿蒙的 ArkUI 是 声明式 UI 框架,使用装饰器改变变量行为。

状态管理类

@State

组件内部状态,用于定义组件私有状态,状态变化会自动触发 UI 刷新。
只属于当前组件,子组件不能直接修改。
@State 装饰的属性必须要设置初始值。

@Component
export struct Foo {
  @State count: number = 0

  build() {
    Column() {
      Button("Add")
        .onClick(() => {
          this.count++
        })
      Text(this.count.toString())
    }
    .height("100%")
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

父子双向绑定,子组件引用父组件状态,并且可以修改父组件状态。

@Component
export struct Parent {
  @State count: number = 0

  build() {
    Column() {
      Button("parent add")
        .onClick(() => {
          this.count++
        })
      Text("parent count:" + this.count)
      Child({ count: this.count })
    }
    .height("100%")
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

@Component
export struct Child {
  @Link count: number

  build() {
    Column() {
      Button("child Add")
        .onClick(() => {
          this.count++
        })
      Text("child count:" + this.count)
    }
  }
}

@Prop

父组件传入只读数据,子组件修改不影响父组件状态

@Component
export struct Parent {
  @State count: number = 0

  build() {
    Column() {
      Button("parent add")
        .onClick(() => {
          this.count++
        })
      Text("parent count:" + this.count)
      Child({ count: this.count })
    }
    .height("100%")
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

@Component
export struct Child {
  @Prop count: number

  build() {
    Column() {
      Button("child Add")
        .onClick(() => {
          this.count++
        })
      Text("child count:" + this.count)
    }
  }
}

@Provide @Consume

@Provide 向任意层级的子孙组件提供数据,需要子孙组件搭配 @Consume 来消费 Provide 数据(构造子孙组件不再需要传递该数据)。

@State + @Link 仅用于父子组件双向绑定数据,@Provide + @Consume 可以用于父组件与任意层级子孙组件之间传递数据。

@Component
export struct Parent {
  @Provide count: number = 0

  build() {
    Column() {
      Button("parent add")
        .onClick(() => {
          this.count++
        })
      Text("parent count:" + this.count)
      Child()
    }
    .height("100%")
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

@Component
export struct Child {
  @Consume count: number

  build() {
    Column() {
      Button("child Add")
        .onClick(() => {
          this.count++
        })
      Text("child count:" + this.count)
    }
  }
}

@Watch

监听状态变化

@Component
export struct Foo {
  // 当 count 改变时,会调用 onCountChange
  @State @Watch("onCountChange") count: number = 0

  build() {
    Column() {
      Button("Add")
        .onClick(() => {
          this.count++
        })
      Text(this.count.toString())
    }
    .height("100%")
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }

  onCountChange() {
    console.log("count 变化了", this.count)
  }
}

数据对象

@Observed

让对象可观察

@Observed
class User {
  name: string = ""
  age: number = 0
}

User 对象内部字段变化 → 自动触发 UI 更新 不加 @Observed → 修改对象内部字段,UI 不会刷新

绑定对象属性

@Link 不会监听对象内部字段变化,所以 @Link 大多只用于基本类型,对象类型必须用 @ObjectLink 才能保证响应式同步。

UI 能力

@Builder @BuilderParam

@Builder 声明一个可复用的 UI 构建函数。需要注意每个组件(用 @Component struct 定义)都有固定签名的 build 方法,这个 build 方法不是普通函数,它是组件生命周期的一部分,框架内部会自动当作 Builder 来执行,不需要再加 @Builder。

@BuilderParam 把一个 @Builder UI 构建函数作为参数传给组件,它允许 父组件决定子组件内部某一块 UI 怎么画。

@Component
export struct Parent {
  build() {
    Column() {
      this.buildItem("haha")
      Child({
        itemBuilder: this.buildItem
      })
    }
    .backgroundColor(Color.White)
    .height("100%")
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }

  @Builder
  buildItem(text: string) {
    Text(text)
  }
}

@Component
export struct Child {
  @BuilderParam itemBuilder: (text: string) => void

  build() {
    Column() {
      this.itemBuilder("Hello")
    }
  }
}

组件相关

@Component 声明组件

@Entry 页面入口

@Preview IDE 预览

@Reusable 可复用组件