# 13.3:@Prop

@Prop 装饰器也是最基础的状态装饰器,它装饰的变量可以和父组件之间建立单向的同步关系,也就是说父组件把自身的状态变量传递给子组件内 @Prop 装饰的变量后,的数据源更改会覆盖到子组件内相对于 @State 来说它只能用于子组件内部,它修饰的 状态变量 不允许本地初始化,只能从父组件传递。

# 13.3.1:约束与限制

  • @Prop 装饰器不能用在 @Entry 装饰的组件内:

    @Prop 装饰器不能用在 @Entry 装饰的组件内,否则编译报错:The @Entry component 'XXX' cannot have the @Prop property 'XXX'.

  • @Prop 修饰的状态变量必须初始化或者由父组件传递:

    @Prop 装饰器装饰的变量要么本地进行初始化要么由父组件传递进来,否则编译报错:The @Provide property 'XXX' must be specified a default value.

  • @Prop 装饰符修饰的状态是单向的:

    @Prop 装饰的变量可以和父组件建立单向的同步关系,当父组件内的状态数据变化时,与之关联的子组件内的 @Prop 装饰的变量都会更新,反之 @Prop 装饰的变量更改不会影响其父组件。

# 13.3.2:@Prop的简单使用

@Prop 的使用和上一章节讲述的 @State 用法类似,在变量前添加 @State 即可,需要说明的是由 @Prop 装饰的变量必须要 指定类型本地初始化,如果本地未初始化则需要从父组件传递,父组件的数据可以是有状态的也可以是无状态的,简单样例如下所示:

@Entry @Component struct Page_03_prop {

  @State message: string = new Date().getTime().toString() // 父组件内定义的状态变量
  tempValue: string = "tempValue"                          // 父组件内定义的无状态变量

  build() {
    Column({space: 10}) {
      Text("time = " + this.message)
        .fontSize(30)
        .onClick(() => {
          this.message = new Date().getTime().toString()   // 更新状态变量的值
          this.tempValue = this.message                    // 更新无状态变量的值
        })

      CustomButton1()                         // 使用子组件CustomButton1,不传数据

      CustomButton1({btnName: this.message})  // 使用子组件CustomButton1,传递数据

      CustomButton2({btnName: this.message})  // 使用子组件CustomButton2,传递父组件的有状态数据
      CustomButton2({btnName: this.tempValue})// 使用子组件CustomButton2,必须父组件的无状态传递数据
    }
    .width('100%')
    .height("100%")
  }
}

@Component struct CustomButton1 {

  @Prop btnName: string = "10086" // 本地已经初始化,如果从父组件传递进来,
                                  // 那么父组件内的数据源如果是状态数据且发生了变更
                                  // 则会覆盖本地的数据,否则不会影响本地的数据。

  build() {
    Row({space: 10}) {
      Image($r("app.media.app_logo"))
        .size({width: 18, height: 18})
      Text("btn1 = " + this.btnName)
        .fontSize(22)
    }
    .padding({left: 20, right: 20, top: 5, bottom: 5})
    .backgroundColor("#aabbcc")
    .borderRadius(8)
    .onClick(() => {
      this.btnName = new Date().getTime().toString()
    })
  }
}

@Component struct CustomButton2 {

  @Prop btnName: string  // 本地已经初始化,如果从父组件传递进来,
                         // 那么父组件内的数据源如果是状态数据且发生了变更
                         // 则会覆盖本地的数据,否则不会影响本地的数据。

  build() {
    Row({space: 10}) {
      Image($r("app.media.app_logo"))
        .size({width: 18, height: 18})
      Text("btn2 = " + this.btnName)
        .fontSize(22)
    }
    .padding({left: 20, right: 20, top: 5, bottom: 5})
    .backgroundColor("#aabbcc")
    .borderRadius(8)
    .onClick(() => {
      this.btnName = new Date().getTime().toString()
    })
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

样例运行结果如下图所示:

13_3_2_1

由上述样例可知,自定义子组件 CustomButton1 添加了 @Prop 装饰的状态变量 btnName 并且赋予了初始值,那么使用该自组件时父组件可以传值也可以不传值;自定义子组件 CustomButton2 也添加了 @Prop 装饰的状态变量 btnName 但该属性没有初始化,因此在使用该组件时必须由父组件传值来初始化 btnName,此时父组件传递进来的数据可以是有状态的也可以是无状态的,如果是有状态的,那么父组件的状态数据若发生变化则会同步到子组件里,反之子组件的状态数据发生变化则不影响父组件。

# 13.3.3:@Prop的作用域

@Prop 装饰器装饰的变量是当前组件私有的,只能在当前组件范围内访问,简单样例如下所示:

@Entry @Component struct Page_03_prop {

  @State message: string = new Date().getTime().toString()

  build() {
    Column({space: 10}) {
      Text("time = " + this.message)
        .fontSize(30)
        .onClick(() => {
          this.message = new Date().getTime().toString()
        })

      CustomButton({btnName: this.message})
    }
    .width('100%')
    .height("100%")
  }
}

@Component struct CustomButton {

  @Prop btnName: string = "10086"

  build() {
    Row({space: 10}) {
      Image($r("app.media.app_logo"))
        .size({width: 18, height: 18})
      Text("btn1 = " + this.btnName)
        .fontSize(22)
    }
    .padding({left: 20, right: 20, top: 5, bottom: 5})
    .backgroundColor("#aabbcc")
    .borderRadius(8)
    .onClick(() => {
      this.btnName = new Date().getTime().toString()
    })
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

样例运行结果如下图所示:

13_3_3_1

由上述样例可知:父组件 Page_03_prop 和子组件 CustomButton 内部都定义了状态数据状态数据 messagebtnName,在使用的时候父组件传递了自己的状态数据给子组件,因此父子组件的状态数据 messagebtnName 就建立了单向的关联关系,一旦 message 的值变化就会同步更新到 btnName,反之 btnName 的值变化不会影响到 message

# 13.3.4:@Prop支持的数据类型

@Prop 装饰器目前支持的数据类型主要如下:

  • 简单数据类型

    简单数据类型目前支持的类型有: number, boolean, string, enum。简单样例如下所示:

    enum ColorType {
      R,
      G,
      B
    }
    
    @Entry @Component struct Page_03_prop {
    
      @State message1: string  = 'Hello World' // 定义 string  类型
      @State message2: number  = 10086         // 定义 number  类型
      @State message3: boolean = false         // 定义 boolean 类型
      @State message4: ColorType = ColorType.R // 定义  enum   类型
    
      build() {
        Column({space: 10}) {
          CustomButton({
            message1: this.message1,
            message2: this.message2,
            message3: this.message3,
            message4: this.message4,
          })
        }
        .width('100%')
        .height("100%")
      }
    }
    
    @Component struct CustomButton {
    
      @State message1: string  = 'Hello aaaaa' // 定义 string  类型
      @State message2: number  = 1234          // 定义 number  类型
      @State message3: boolean = false         // 定义 boolean 类型
      @State message4: ColorType = ColorType.G // 定义  enum   类型
    
      build() {
        Column({space: 10}) {
          Text("message1 = " + this.message1)
            .fontSize(22)
            .onClick(() => {
              this.message1 = "Hello《ArkUI实战》";
            })
          Text("message2 = " + this.message2)
            .fontSize(22)
            .onClick(() => {
              this.message2 = 10010;
            })
          Text("message3 = " + this.message3)
            .fontSize(22)
            .onClick(() => {
              this.message3 = true;
            })
          Text("message4 = " + this.message4)
            .fontSize(22)
            .onClick(() => {
              this.message4 = ColorType.B
            })
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59

    样例运行结果如下图所示:

    13_3_4_1
  • 简单数组类型

    简单数据类型 目前支持的有: number, boolean, string, enum,笔者把由它们组成的 数组 简称为简单数组,目前简单数组支持的操作为:数组重新赋值数组单项赋值数组数据添加数组数据删除,以上支持的操作会引起相关组件的重绘。简单样例如下所示:

请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2

中央网信办互联网违法和不良信息举报中心

天津市互联网违法和不良信息举报中心