@State

  • 在声明式UI中,是以状态驱动视图更新:
    image.png
    • 状态(State):指驱动视图更新的数据(被装饰器标记的变量)
    • 视图(View):基于UI描述渲染得到用户界面
    • 被State修饰的变量才能更新
  • 说明:
  1. @State装饰器标记的变量必须初始化,不能为空值。
  2. @State支持Object、class、string、number、boolean、enum类型以及这些类型的数组。
  3. 嵌套类型以及数组中的对象属性无法触发视图更新。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @State message: string = 'Hello World !!'  

    build() {
    column(){
    Text(this.message)
    .fontSize(30)
    .fontWeight(FontWeight.Bold)
    .fontColor('#36D')
    .onClick(() => {
    this.message = 'Hello ArkTS!'
    })

@Prop & @Link

  • 当父子组件之间需要数据同步时,可以使用@Prop和@Link装饰器。
    image.png
@Prop @Link
同步类型 单向同步 双向同步
允许装饰的变量类型 - @Prop只支持string、number、boolean、enum类型
- 父组件对象类型,子组件是对象属性
- 不可以是数组、any
- 父子类型一直:string、number、boolean、enum、object、class,以及他们的数组
- 数组中元素增、删、替换会引起刷新
- 嵌套类型以及数组中的对象属性无法触发视图更新
初始化方式 不允许子组件初始化 父组件传递,禁止子组件初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Entry
@Component
struct PropPage {
@State totalTask: number = 0 //父组件创建的变量
Task({totalTask: this.totalTask}) //将变量传递到子组件
TaskList({totalTask: $totalTask}) //@Link需要传递的是引用,而不是值,所以需要用$美元符号
}

@Component
struct Task {
@Prop totalTask: number //子组件不允许初始化
}
//@Link用法类似,@Link则是双向同步刷新
@Component
struct TaskList {
@Link totalTask: number
}

@Provide & @Consume

  • @Provide和@Consume可以跨组件提供类似于@State和@Link的双向同步
    image.png
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Entry
    @Component
    struct PropPage {
    @Provide totalTask: number = 0 //父组件创建的变量
    Task() //不需要传递参数
    }

    @Component
    struct Task {
    @Consume totalTask: number //子组件不允许初始化
    }
  • 但是性能损耗也比较大,无需跨组件时尽量使用@Prop和@Link

@Observed & @ObjectLink

  • @ObjectLink和@Observed装饰器用于在涉及嵌套对象或数组元素为对象的场景中进行双向数据同步
  • 解决嵌套对象里的对象属性变更无法刷新和数组里边的元素对象属性无法刷新的问题
  • 解决方法:
  1. 给对象添加@Observed装饰器
  2. 同时给嵌套的对象加上@ObjectLink装饰器
  3. 一般情况需要将它作为参数传给一个组件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Observed
    class Task{ //创建的对象
    static id: number = 1
    //...
    }

    @Entry
    //主页面部分
    @State task: Task[] = []
    handleTaskChange(){
    this.totalTask = this.tasks.length
    this.finishTask = this.tasks.filter(item => item.finished).length
    }
    //...
    TaskItem({item:item, onTaskChange: this.handleTaskChange.bind(this)}) //传递时this会缺失,所以用bind传递this

    @Component
    struct TaskItem {
    @ObjectLink item: Task
    onTaskChange: () => void //当子组件需要使用父组件的函数,可以传进来
    //...
    }