1、前言

我们在上一章学习了@State装饰器,@State装饰器的作用范围仅仅在当前组件,接下来,我们讨论如何从父组件中传入参数到子组件,让子组件随着父组件的状态发生变化。本章将要介绍的就是:@Props装饰器。

2、@Props装饰器

@Prop装饰的变量可以和父组件建立单向的同步关系。@Prop装饰的变量是可变的,但是变化不会同步回其父组件。

  • @Prop变量允许在本地修改和初始化,但修改后的变化不会同步回父组件。

  • 当父组件中的数据源更改时,与之相关的@Prop装饰的变量都会自动更新。如果子组件已经在本地修改了@Prop装饰的相关变量值,而在父组件中对应的@State装饰的变量被修改后,子组件本地修改的@Prop装饰的相关变量值将被覆盖。

  • @Prop装饰器不能在@Entry装饰的自定义组件中使用。

  • 装饰器允许装饰的变量类型有:string、number、boolean、enum类型。不支持any,不允许使用undefined和null。

  • 装饰的变量必须指定类型,在父组件中,传递给@Prop装饰的值不能为undefined或者null;

  • @Prop装饰的变量和父组件状态变量类型相同,即@Prop : S和@State : S

  • 虽然说@Props装饰的变量可由父组件初始化,但使用范围依旧只能在组件内访问。

核心代码结构如下:

@Component
struct Child {
// 子组件中的@Props变量,可以被父组件初始化
  @Prop count: number;
} @Entry
struct Parent {
  @State parentCount:number = 1;
  build() {
  // 此时,父组件就将本地parentCount变量传递给了子组件
  // 当parentCount发生变化时,子组件也会刷新
  Child({count: this.parentCount});
  }
}

3、@Props装饰器的简单使用Demo

以下示例是@State到子组件@Prop简单数据同步,

父组件ParentComponent的状态变量countDownStartValue初始化子组件CountDownComponent中@Prop装饰的count,

点击“Try again”,count的修改仅保留在CountDownComponent,不会同步给父组件ParentComponent。

ParentComponent的状态变量countDownStartValue的变化将重置CountDownComponent的count。

@Component
struct CountDownComponent {
@Prop count: number;
costOfOneAttempt: number = 1; build() {
Column() {
if (this.count > 0) {
Text(`You have ${this.count} Nuggets left`)
} else {
Text('Game over!')
}
// @Prop装饰的变量不会同步给父组件
Button(`Try again`).onClick(() => {
this.count -= this.costOfOneAttempt;
})
}
}
} @Entry
@Component
struct ParentComponent {
@State countDownStartValue: number = 10; build() {
Column() {
Text(`Grant ${this.countDownStartValue} nuggets to play.`)
// 父组件的数据源的修改会同步给子组件
Button(`+1 - Nuggets in New Game`).onClick(() => {
this.countDownStartValue += 1;
})
// 父组件的修改会同步给子组件
Button(`-1 - Nuggets in New Game`).onClick(() => {
this.countDownStartValue -= 1;
}) CountDownComponent({ count: this.countDownStartValue, costOfOneAttempt: 2 })
}
}
}

在上面的示例中:

  1. CountDownComponent子组件首次创建时其@Prop装饰的count变量将从父组件@State装饰的countDownStartValue变量初始化,界面如下:

  1. 按“+1”或“-1”按钮时,父组件的@State装饰的countDownStartValue值会变化,这将触发父组件重新渲染,在父组件重新渲染过程中会刷新使用countDownStartValue状态变量的UI组件并单向同步更新CountDownComponent子组件中的count值;

  1. 更新count状态变量值也会触发CountDownComponent的重新渲染,在重新渲染过程中,评估使用count状态变量的if语句条件(this.count > 0),并执行true分支中的使用count状态变量的UI组件相关描述来更新Text组件的UI显示;

  2. 当按下子组件CountDownComponent的“Try again”按钮时,其@Prop变量count将被更改,但是count值的更改不会影响父组件的countDownStartValue值;

  1. 父组件的countDownStartValue值会变化时,父组件的修改将覆盖掉子组件CountDownComponent中count本地的修改。

由于有@State装饰器的经验,学习@Props起来就得心应手了。到此,我们基本也就掌握了@Props装饰器的使用了。

趁热打铁,我们可能就会问了,@Props组件只能由父组件到子组件单向传递,那我想实现双向传递怎么办呢?那就需要用到@Link装饰器了。

4、@Link装饰器

@Link装饰器与@Props装饰器的用法几乎一样,区别只是@Props装饰器是父组件向子组件单向同步,而@Link装饰器是子组件和父组件双向同步。

我们平时使用@Link装饰器就和@Props差不多,有一个区别:@Link装饰器的属性不能本地初始化。

直接上一段Demo:

点击父组件ShufflingContainer中的“Parent View: Set yellowButton” 和 “Parent View: Set GreenButton”,可以从父组件将变化(控件长度)同步给子组件。

1.点击子组件GreenButton和YellowButton中的Button,子组件会发生相应变化,将变化同步回父组件。因为@Link是双向同步,会将变化同步给@State。

2.当点击父组件ShufflingContainer中的Button时,@State变化,也会同步给@Link,子组件也会发生对应的刷新。

代码如下:

class GreenButtonState {
width: number = 0; constructor(width: number) {
this.width = width;
}
} @Component
struct GreenButton {
@Link greenButtonState: GreenButtonState; build() {
Button('Green Button')
.width(this.greenButtonState.width)
.height(40)
.backgroundColor('#64bb5c')
.fontColor('#FFFFFF,90%')
.onClick(() => {
if (this.greenButtonState.width < 700) {
// 更新class的属性,变化可以被观察到同步回父组件
this.greenButtonState.width += 60;
} else {
// 更新class,变化可以被观察到同步回父组件
this.greenButtonState = new GreenButtonState(180);
}
})
}
} @Component
struct YellowButton {
@Link yellowButtonState: number; build() {
Button('Yellow Button')
.width(this.yellowButtonState)
.height(40)
.backgroundColor('#f7ce00')
.fontColor('#FFFFFF,90%')
.onClick(() => {
// 子组件的简单类型可以同步回父组件
this.yellowButtonState += 40.0;
})
}
} @Entry
@Component
struct ShufflingContainer {
@State greenButtonState: GreenButtonState = new GreenButtonState(180);
@State yellowButtonProp: number = 180; build() {
Column() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
// 简单类型从父组件@State向子组件@Link数据同步
Button('Parent View: Set yellowButton')
.width(312)
.height(40)
.margin(12)
.fontColor('#FFFFFF,90%')
.onClick(() => {
this.yellowButtonProp = (this.yellowButtonProp < 700) ? this.yellowButtonProp + 40 : 100;
})
// class类型从父组件@State向子组件@Link数据同步
Button('Parent View: Set GreenButton')
.width(312)
.height(40)
.margin(12)
.fontColor('#FFFFFF,90%')
.onClick(() => {
this.greenButtonState.width = (this.greenButtonState.width < 700) ? this.greenButtonState.width + 100 : 100;
})
// class类型初始化@Link
GreenButton({ greenButtonState: $greenButtonState }).margin(12)
// 简单类型初始化@Link
YellowButton({ yellowButtonState: $yellowButtonProp }).margin(12)
}
}
}
}

5、结语

至此,我们在@State装饰器的基础上又学习了@Props装饰器和@Link装饰器,@Props装饰器用于接受来自父组件的变量,@Link也用于接受来自父组件的变量,但额外的,@Link装饰器在子组件中被修改后,父组件中对应的值也会发生改变。

剩下的状态装饰器请持续关注 “鸿蒙UI开发快速入门 —— part08 ”

鸿蒙UI开发快速入门 —— part07:组件状态管理之@Prop/@Link装饰器的更多相关文章

  1. Transform组件C#游戏开发快速入门

    Transform组件C#游戏开发快速入门大学霸 组件(Component)可以看作是一类属性的总称.而属性是指游戏对象上一切可设置.调节的选项,如图2-8所示.本文选自C#游戏开发快速入门大学霸   ...

  2. HealthKit开发快速入门教程之HealthKit框架体系创建健康AppID

    HealthKit开发快速入门教程之HealthKit框架体系创建健康AppID HealthKit开发准备工作 在开发一款HealthKit应用程序时,首先需要讲解HealthKit中有哪些类,在i ...

  3. HealthKit开发快速入门教程之HealthKit开发概述简介

    HealthKit开发快速入门教程之HealthKit开发概述简介 2014年6月2日召开的年度开发者大会上,苹果发布了一款新的移动应用平台,可以收集和分析用户的健康数据.该移动应用平台被命名为“He ...

  4. Apple Watch开发快速入门教程

     Apple Watch开发快速入门教程  试读下载地址:http://pan.baidu.com/s/1eQ8JdR0 介绍:苹果为Watch提供全新的开发框架WatchKit.本教程是国内第一本A ...

  5. SpringBoot开发快速入门

    SpringBoot开发快速入门 目录 一.Spring Boot 入门 1.Spring Boot 简介 2.微服务 3.环境准备 1.maven设置: 2.IDEA设置 4.Spring Boot ...

  6. HealthKit开发快速入门教程之HealthKit数据的操作

    HealthKit开发快速入门教程之HealthKit数据的操作 数据的表示 在HealthKit中,数据是最核心的元素.通过分析数据,人们可以看到相关的健康信息.例如,通过统计步数数据,人们可以知道 ...

  7. 游戏控制杆OUYA游戏开发快速入门教程

    游戏控制杆OUYA游戏开发快速入门教程 1.2.2  游戏控制杆 游戏控制杆各个角度的视图,如图1-4所示,它的硬件规格是本文选自OUYA游戏开发快速入门教程大学霸: 图1-4  游戏控制杆各个角度的 ...

  8. WPF开发快速入门【7】WPF的拖放功能(Drag and Drop)

    概述 本文描述WPF的拖放功能(Drag and Drop). 拖放功能涉及到两个功能,一个就是拖,一个是放.拖放可以发生在两个控件之间,也可以在一个控件自己内部拖放.假设界面上有两个控件,一个Tre ...

  9. ReactJS入门2:组件状态

    React组件可以简单看做是包含props和states的函数. 上一节总结了创建新组建和数据属性的传递.本节主要讲解组件的状态. React认为UI是不同状态的展现.在React中,开发者只需更新组 ...

  10. 【翻译】WPF应用程序模块化开发快速入门(使用Prism+MEF)

    编译并运行快速入门 需要在VisualStudio 2010上运行此快速入门示例 代码下载:ModularityWithMef.zip 先重新生成解决方案 再按F5运行此示例 说明: 在此快速入门示例 ...

随机推荐

  1. 阿里面试让聊一聊Redis 的内存淘汰(驱逐)策略

    大家好,我是 V 哥,粉丝小A面试阿里,说被问到 Redis 的内存淘汰策略的问题,整理这个笔记给他参考,也分享给大家,如果你遇到这个问题,会怎么回答呢? Redis 的内存淘汰策略是指当Redis的 ...

  2. LeetCode 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit (绝对差不超过限制的最长连续子数组)

    给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit . 如果不存在满足条件的子数组,则返回 ...

  3. 推荐一款轻量级 eBPF 前端工具 ply

    1 Overview ply 是 eBPF 的 front-end 前端工具之一,专为 embedded Linux systems 开发,采用 C 语言编写,只需 libc 和内核支持 BPF 就可 ...

  4. Java日期时间API系列23-----Jdk8中java.time包中的新的日期时间API类,获取准确开始时间00:00:00,获取准确结束时间23:59:59等

    有时候,往往需要统计某个时间区间的销量等问题,这就需要准确的起始时间,获取准确开始时间00:00:00,获取准确结束时间23:59:59.下面增加了一一些方法,获取当天起始时间,昨天起始时间,当前月第 ...

  5. iOS中异常处理机制使用小结

    在iOS开发中经常会由于数组越界,添加数据为空,通信或者文件错误,内存溢出导致程序终端运行而引入异常处理机制.常用的处理方式是try catch机制.不过有几个专业术语需要解释,异常句柄.异常处理域断 ...

  6. Docker升阶

    一.Docker镜像 镜像的定义:镜像是一种轻量级.可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码.运行时需要的库以及环境变量和 ...

  7. 枚举(C语言)

    1.枚举定义 枚举是 C 语言中的一种基本数据类型,用于定义一组具有离散值的常量,它可以让数据更简洁,更易读. 枚举类型通常用于为程序中的一组相关的常量取名字,以便于程序的可读性和维护性. 定义一个枚 ...

  8. Java学习十六—掌握注解:让编程更简单

    一.关于注解 1.1 简介 Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据.它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译.部署或运行时进 ...

  9. Min-25 筛小记

    Min-25 筛 参考 \(\text{OI-Wiki}\) 和 2018 集训队论文 朱震霆<一些特殊的数论函数求和问题>. \(\text{Min-25}\) 的本质是埃式筛和数论分块 ...

  10. C++ stl锁的使用

    我们在日常开发中经常要用到锁,这里记录一下实际开发过程中stl提供的锁的使用. 1.读写锁 读写锁算是用到的比较多的一种类型,主要实现对于同一个共享数据区,一个时间点只能有一个线程进行写(增删改),但 ...