HarmonyOS 中arkTS不同状态装饰器的理解@State@Prop@Link@Observed和ObjectLink@Provide和@Consume@Watch

状态装饰器我知道的最早是在facebook公司为了解决他们项目过大,庞大代码更新UI比较慢,代码耦合度高想的解决方案,然后Google 和 IOS 都进行了效仿。
状态装饰器 ---- 主要解决“跨级”通信
“”“自我理解
声明式UI 就是懒人的福音,他更接近自然语言,但是UI虽然可以用自然语言进行描述,但是无法用自然语言直接修改,这个时候状态装饰器就是解决这个问题的。
级别包含: 自己,父级别,爷爷级别,模组级别,模块级别。”“”"

第一:解决自己的问题:@state 装饰器
@State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。

@State状态数据具有以下特征

支持多种类型数据:支持class、number、boolean、string强类型数据的值类型和引用类型,以及这些强类型构成的数组,即Array、Array、Array、Array。不支持object和any。
支持多实例:组件不同实例的内部状态数据独立。
内部私有:标记为@State的属性是私有变量,只能在组件内访问。
需要本地初始化:必须为所有@State变量分配初始值,变量未初始化可能导致未定义的框架异常行为。
创建自定义组件时支持通过状态变量名设置初始值:在创建组件实例时,可以通过变量名显式指定@State状态变量的初始值。。

第二: 单项解决儿子的问题:@Prop 装饰器(父亲页面数据变化告诉孩子,孩子数据变化不告诉父亲,所以要明确数据的修改是在父组件还是子组件,在儿子里面用)
@Prop与@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但变量的更改不会通知给父组件,父组件变量的更改会同步到@prop装饰的变量,即@Prop属于单向数据绑定。

@Prop状态数据具有以下特征:

支持简单类型:仅支持number、string、boolean等简单数据类型;
私有:仅支持组件内访问;
支持多个实例:一个组件中可以定义多个标有@Prop的属性;
创建自定义组件时将值传递给@Prop变量进行初始化:在创建组件的新实例时,必须初始化所有@Prop变量,不支持在组件内部进行初始化。

第三:双向解决 父亲和儿子问题@Link
(父布局数据变化告诉儿子,儿子数据变化也告诉父亲,比较乖,在儿子里面用)
@Link装饰的变量可以和父组件的@State变量建立双向数据绑定:

支持多种类型:@Link支持的数据类型与@State相同,即class、number、string、boolean或这些类型的数组;
私有:仅支持组件内访问;
单个数据源:父组件中用于初始化子组件@Link变量的必须是父组件定义的状态变量;
双向通信:子组件对@Link变量的更改将同步修改父组件中的@State变量;
创建自定义组件时需要将变量的引用传递给@Link变量,在创建组件的新实例时,必须使用命名参数初始化所有@Link变量。@Link变量可以使用@State变量或@Link变量的引用进行初始化,@State变量可以通过​​'$'​​操作符创建引用。

父组件中用@State 定义的变量 在初始化子组件的使用用$ 引用
在这里插入图片描述在这里插入图片描述
子组件中用@Link 定义变量在这里插入图片描述--------------------------------------------------------------------------------------------------

组合使用:
(如果父组件A中有个变量@state 的变量A,子组件B中@Prop 变量B,子组件C中@Link 变量C, 当子组件B 和 子组件C 同时在父组件A中使用的时候,变量A变化 — 变量B 和变量C 都会变化,当C 变化的时候----- 变量A 和B 都会变化 ,但是当变量B变化的时候 — A 和C 都不会变化)

第四:解决父亲和儿子中,部分数据变化问问题
@Observed和ObjectLink数据管理(以下内容是抄的)

  ○  类要被@Observed装饰器所装饰。

  ○  不支持简单类型参数,可以使用@Prop进行单向同步。

@ObjectLink装饰的变量是不可变的。

  ○  属性的改动是被允许的,当改动发生时,如果同一个对象被多个@ObjectLink变量所引用,那么所有拥有这些变量的自定义组件都会被通知进行重新渲染。

@ObjectLink装饰的变量不可设置默认值。

  ○  必须让父组件中有一个由@State、@Link、@StorageLink、@Provide或@Consume装饰的变量所参与的TS表达式进行初始化。

@ObjectLink装饰的变量是私有变量,只能在组件内访问。

使用方法:
@Observed用于类,@ObjectLink用于变量。
@ObjectLink装饰的变量类型必须为类(class type)。
父类中用@State、@Link、@StorageLink、@Provide或@Consume装饰的变量所参与

自我理解: 当后台返回一个数组的时候,父布局只用数组中的某一元素的时候使用@ObjectLink,不需要将整个数组传递到子组件,当子组件中用整个数组的时候可以用@Link 装饰器,如果有哪位大佬新的理解或者补充,请评论区留言


第五上内容解决了父亲和儿子数据同步问题,以下内容就是解决爷爷和孙子数据双向同步问题@Provide和@Consume
@Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。@Consume在感知到@Provide数据的更新后,会触发当前自定义组件的重新渲染。
使用方法:
1 父类中用@Provide(“变量别称”)变量名 : 类型 = 初始化
(@Provide(“orderId”) orderId: number = 0;)
2 孙子类中用@Consume(“变量别称”)变量名 : 类型
@Consume(“orderId”) orderId: number
3 在父类中调用 改变值,孙子就知道(孙子就是厉害,都不需要传递参数,就知道爷爷的变量变化了)

第六:己,儿子,孙子结构内的数据都解决了,那么在业务场景中有些复杂的业务场景是通过逻辑修改才会修改UI的,如何做呢?
使用@Watch(监听数据变化,进行回调方法,在方法内更新UI的状态)
@State @Watch(“onChanged”) Selected: number = 0
如上所示,给状态变量增加一个@Watch装饰器,通过@Watch注册一个回调方法onChanged, 当状态变量count被改变时, 触发onChanged回调。
比如中将的规则:页面有三个礼盒,礼盒a,礼盒b,礼盒c,服务器设置的中奖礼盒为礼盒B,如果中间发放100元现金,如果没有中将奖励10元,
选择礼盒ID,中奖礼盒ID,选择后结果展示
@Entry
@Component
struct TestA {
@State @Watch(“onChanged”) Selected: number = 0 ; // 选择的礼盒ID
@State winningID: number = 2 ;// 中奖的礼盒ID
@State isChange: boolean = false;

aboutToAppear() {

}
onChanged(): void {

this.isChange = (this.Selected == this.winningID? true : false)

}

build() {
Column() {
Button(‘礼盒A’)
.margin(15)
.onClick(() => {
this.Selected = 1
})
Button(‘礼盒B’)
.margin(15)
.onClick(() => {
this.Selected = 2
})
Button(‘礼盒C’)
.margin(15)
.onClick(() => {
this.Selected = 3
})
if(this.isChange){
Text(‘恭喜中奖100元现金’)
.fontSize(30)
}else if(this.Selected!=0 && !this.isChange){
Text(‘恭喜中奖10元现金’)
.fontSize(30)
}

}

}
}
小编才疏学浅,本篇内容参考了这个文章,大家有什么补充欢迎留言,协助更多的人提高认知,谢谢。
https://ost.51cto.com/posts/23028

你可能感兴趣的:(harmonyos)