鸿蒙的 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)
}
}
@Link
父子双向绑定,子组件引用父组件状态,并且可以修改父组件状态。
@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 不会刷新
@ObjectLink
绑定对象属性
@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")
}
}
}