鸿蒙UI开发快速入门 —— part07:组件状态管理之@Prop/@Link装饰器
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 })
}
}
}
在上面的示例中:
- CountDownComponent子组件首次创建时其@Prop装饰的count变量将从父组件@State装饰的countDownStartValue变量初始化,界面如下:
- 按“+1”或“-1”按钮时,父组件的@State装饰的countDownStartValue值会变化,这将触发父组件重新渲染,在父组件重新渲染过程中会刷新使用countDownStartValue状态变量的UI组件并单向同步更新CountDownComponent子组件中的count值;
更新count状态变量值也会触发CountDownComponent的重新渲染,在重新渲染过程中,评估使用count状态变量的if语句条件(this.count > 0),并执行true分支中的使用count状态变量的UI组件相关描述来更新Text组件的UI显示;
当按下子组件CountDownComponent的“Try again”按钮时,其@Prop变量count将被更改,但是count值的更改不会影响父组件的countDownStartValue值;
- 父组件的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装饰器的更多相关文章
- Transform组件C#游戏开发快速入门
Transform组件C#游戏开发快速入门大学霸 组件(Component)可以看作是一类属性的总称.而属性是指游戏对象上一切可设置.调节的选项,如图2-8所示.本文选自C#游戏开发快速入门大学霸 ...
- HealthKit开发快速入门教程之HealthKit框架体系创建健康AppID
HealthKit开发快速入门教程之HealthKit框架体系创建健康AppID HealthKit开发准备工作 在开发一款HealthKit应用程序时,首先需要讲解HealthKit中有哪些类,在i ...
- HealthKit开发快速入门教程之HealthKit开发概述简介
HealthKit开发快速入门教程之HealthKit开发概述简介 2014年6月2日召开的年度开发者大会上,苹果发布了一款新的移动应用平台,可以收集和分析用户的健康数据.该移动应用平台被命名为“He ...
- Apple Watch开发快速入门教程
Apple Watch开发快速入门教程 试读下载地址:http://pan.baidu.com/s/1eQ8JdR0 介绍:苹果为Watch提供全新的开发框架WatchKit.本教程是国内第一本A ...
- SpringBoot开发快速入门
SpringBoot开发快速入门 目录 一.Spring Boot 入门 1.Spring Boot 简介 2.微服务 3.环境准备 1.maven设置: 2.IDEA设置 4.Spring Boot ...
- HealthKit开发快速入门教程之HealthKit数据的操作
HealthKit开发快速入门教程之HealthKit数据的操作 数据的表示 在HealthKit中,数据是最核心的元素.通过分析数据,人们可以看到相关的健康信息.例如,通过统计步数数据,人们可以知道 ...
- 游戏控制杆OUYA游戏开发快速入门教程
游戏控制杆OUYA游戏开发快速入门教程 1.2.2 游戏控制杆 游戏控制杆各个角度的视图,如图1-4所示,它的硬件规格是本文选自OUYA游戏开发快速入门教程大学霸: 图1-4 游戏控制杆各个角度的 ...
- WPF开发快速入门【7】WPF的拖放功能(Drag and Drop)
概述 本文描述WPF的拖放功能(Drag and Drop). 拖放功能涉及到两个功能,一个就是拖,一个是放.拖放可以发生在两个控件之间,也可以在一个控件自己内部拖放.假设界面上有两个控件,一个Tre ...
- ReactJS入门2:组件状态
React组件可以简单看做是包含props和states的函数. 上一节总结了创建新组建和数据属性的传递.本节主要讲解组件的状态. React认为UI是不同状态的展现.在React中,开发者只需更新组 ...
- 【翻译】WPF应用程序模块化开发快速入门(使用Prism+MEF)
编译并运行快速入门 需要在VisualStudio 2010上运行此快速入门示例 代码下载:ModularityWithMef.zip 先重新生成解决方案 再按F5运行此示例 说明: 在此快速入门示例 ...
随机推荐
- QT6框架也能开发Web浏览器应用程序:QT6框架如何编译运行测试WebAssembly应用程序?
QT6框架也能开发Web浏览器应用程序:QT6框架如何编译运行测试WebAssembly应用程序? 简介 本文将介绍如何使用QT6框架开发Web浏览器应用程序,并介绍具体的编译运行测试WebAssem ...
- Flutter Engage China 开发者常见问题解答 | 上篇
再次感谢大家对 Flutter Engage China 活动 的关注和积极参与!我们在活动前后收到了很多来自开发者的反馈和问题,Flutter 团队和演讲嘉宾在直播 Q&A 环节中也针对部分 ...
- 音视频入门-4-ffmpeg命令快速体验音视频开发/ ffmpeg编译过程经历的99八十一难
<1>我的实验所使用的视频文件告知读者 1. 这是我在ubuntu环境上实验使用的视频文件, 我在windows上查看了详细信息,然后拖进ubuntu内,重命名为video-test.mp ...
- C语言实现面向对象方法学的GLib、GObject-初体验
0. 扫盲: GLib是用C写的一些utilities,即C的工具库,和libc/glibc(GNU C Library)没有关系. GLib是 Gtk+ 库和 Gnome 的基础.GLib可以在多个 ...
- 让人眼前一亮的开源项目「GitHub 热点速览」
时隔两周,我又带着让人眼前一亮的开源项目回来了! 告别数据线.蓝牙.WiFi 和网络,只需用手机的摄像头扫描一张动图条形码(需安装应用),就能在设备间传输文件的 libcimbar,一款无需联网和蓝牙 ...
- 八字五行强弱喜用神测算api免费接口_json数据格式_可计算五行打分强弱
八字以木.火.土.金.水去分析其旺弱,而分析之法以月令地支最为有力,其次为时支,再次为日支,最弱为年支,而天干必须见地支有同类或有生自己的五行才有用,因为只有天干一个单独的五行,其力会弱至无用.这个接 ...
- Access to XMLHttpRequest at xxxx from origin xxx has been blocked by CORS policy: No 'Access-Control- Allow-Origin' header is present on the requested resource
错误:控制台报错 : network 自动发起了请求: 解决办法: 找到 \node_modules\sockjs-client\dist\sockjs.js 文件 然后 crtl + g 快捷键跳 ...
- 云原生爱好者周刊:长得最像苹果的 Linux 桌面
云原生一周动态要闻 SUSE 发布 Harvester 0.2.0 IBM 收购容器服务提供商 BoxBoat Kubernetes 和云原生运营报告 2021 发布 适用于 Kubernetes 的 ...
- KubeSphere 在直播应用中的实践
本文是上海站 Meetup 讲师唐明根据其分享内容整理的文章. 引言 目前媒体的主流传播渠道已从传统的报纸.广播.电视转向了互联网,各种视频及社交 App 成为了人们获取资讯的首选途径.苏州市广播电视 ...
- AI实战篇:Spring AI + 混元 手把手带你实现企业级稳定可部署的AI业务智能体
前言 在之前的内容中,我们详细讲解了Spring AI的基础用法及其底层原理.如果还有小伙伴对此感到困惑,欢迎参考下面这篇文章,深入学习并进一步掌握相关知识:https://www.cnblogs.c ...