鸿蒙开发基础库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

UTILS.md 8.9KB

4 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. - # [@State装饰器:组件内状态](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-0000001774279614)
  2. > @State装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI会发生对应的渲染改变。
  3. >
  4. > 在状态变量相关装饰器中,@State是最基础的,使变量拥有状态属性的装饰器,它也是大部分状态变量的数据源。
  5. > @State装饰的变量,与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问,在声明时必须指定其类型和本地初始化。初始化也可选择使用命名参数机制从父组件完成初始化。
  6. >
  7. > @State装饰的变量拥有以下特点:
  8. >
  9. > @State装饰的变量与子组件中的@Prop装饰变量之间建立单向数据同步,与@Link、@ObjectLink装饰变量之间建立双向数据同步。
  10. >
  11. > @State装饰的变量生命周期与其所属自定义组件的生命周期相同。
  12. >
  13. - # [@Prop装饰器:父子单向同步](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-prop-0000001774119942)
  14. > @Prop装饰的变量可以和父组件建立单向的同步关系。@Prop装饰的变量是可变的,但是变化不会同步回其父组件。
  15. >@Prop装饰的变量和父组件建立单向的同步关系:
  16. >
  17. >@Prop变量允许在本地修改,但修改后的变化不会同步回父组件。
  18. >
  19. >当数据源更改时,@Prop装饰的变量都会更新,并且会覆盖本地所有更改。因此,数值的同步是父组件到子组件(所属组件),子组件数值的变化不会同步到父组件。
  20. >
  21. - # [@Link装饰器:父子双向同步](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-link-0000001820999565)
  22. > 子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。
  23. >
  24. > @Link装饰的变量与其父组件中的数据源共享相同的值。
  25. >
  26. > @Link装饰器不能在@Entry装饰的自定义组件中使用。
  27. - # [@Provide装饰器和@Consume装饰器:与后代组件双向同步](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-provide-and-consume-0000001820879589)
  28. > @Provide和@Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,@Provide和@Consume摆脱参数传递机制的束缚,实现跨层级传递。
  29. >
  30. > 其中@Provide装饰的变量是在祖先组件中,可以理解为被“提供”给后代的状态变量。@Consume装饰的变量是在后代组件中,去“消费(绑定)”祖先组件提供的变量。
  31. > @Provide/@Consume装饰的状态变量有以下特性:
  32. >
  33. > @Provide装饰的状态变量自动对其所有后代组件可用,即该变量被“provide”给他的后代组件。由此可见,@Provide的方便之处在于,开发者不需要多次在组件之间传递变量。
  34. >
  35. > 后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递。
  36. >
  37. > @Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,从而导致应用行为异常。
  38. ```typescript
  39. // 通过相同的变量名绑定
  40. @Provide a: number = 0;
  41. @Consume a: number;
  42. // 通过相同的变量别名绑定
  43. @Provide('a') b: number = 0;
  44. @Consume('a') c: number;
  45. @Provide和@Consume通过相同的变量名或者相同的变量别名绑定时,@Provide装饰的变量和@Consume装饰的变量是一对多的关系。不允许在同一个自定义组件内,包括其子组件中声明多个同名或者同别名的@Provide装饰的变量,@Provide的属性名或别名需要唯一且确定,如果声明多个同名或者同别名的@Provide装饰的变量,会发生运行时报错。
  46. ```
  47. - # [@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-observed-and-objectlink-0000001774279618)
  48. > 上文所述的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink装饰器。
  49. > @ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:
  50. >
  51. > 被@Observed装饰的类,可以被观察到属性的变化;
  52. >
  53. > 子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中的属性,这个属性同样也需要被@Observed装饰。
  54. >
  55. > 单独使用@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop使用。
  56. > 使用@Observed装饰class会改变class原始的原型链,@Observed和其他类装饰器装饰同一个class可能会带来问题。
  57. >
  58. > @ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
  59. - # [@Watch装饰器:状态变量更改通知](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-watch-0000001774119954)
  60. > @Watch应用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。
  61. > @Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用。@Watch在ArkUI框架内部判断数值有无更新使用的是严格相等(===),遵循严格相等规范。当在严格相等为false的情况下,就会触发@Watch的回调。
  62. ```typescript
  63. @Component
  64. struct TotalView {
  65. @Prop @Watch('onCountUpdated') count: number = 0;
  66. @State total: number = 0;
  67. // @Watch 回调
  68. onCountUpdated(propName: string): void {
  69. this.total += this.count;
  70. }
  71. build() {
  72. Text(`Total: ${this.total}`)
  73. }
  74. }
  75. @Entry
  76. @Component
  77. struct CountModifier {
  78. @State count: number = 0;
  79. build() {
  80. Column() {
  81. Button('add to basket')
  82. .onClick(() => {
  83. this.count++
  84. })
  85. TotalView({ count: this.count })
  86. }
  87. }
  88. }
  89. ```
  90. - # [$$语法:内置组件双向同步](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-two-way-sync-0000001820999577)
  91. ```typescript
  92. // xxx.ets
  93. @Entry
  94. @Component
  95. struct TextInputExample {
  96. @State text: string = ''
  97. controller: TextInputController = new TextInputController()
  98. build() {
  99. Column({ space: 20 }) {
  100. Text(this.text)
  101. TextInput({ text: $$this.text, placeholder: 'input your word...', controller: this.controller })
  102. .placeholderColor(Color.Grey)
  103. .placeholderFont({ size: 14, weight: 400 })
  104. .caretColor(Color.Blue)
  105. .width(300)
  106. }.width('100%').height('100%').justifyContent(FlexAlign.Center)
  107. }
  108. }
  109. ```
  110. - # [@Track装饰器:class对象属性级更新](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-track-0000001820879601)
  111. > @Track应用于class对象的属性级更新。@Track装饰的属性变化时,只会触发该属性关联的UI更新。
  112. > @Track是class对象的属性装饰器。当一个class对象是状态变量时,@Track装饰的属性发生变化,只会触发该属性关联的UI更新;而未被标记的属性不能在UI中使用。
  113. ```typescript
  114. class LogTrack {
  115. @Track str1: string;
  116. @Track str2: string;
  117. constructor(str1: string) {
  118. this.str1 = str1;
  119. this.str2 = 'World';
  120. }
  121. }
  122. class LogNotTrack {
  123. str1: string;
  124. str2: string;
  125. constructor(str1: string) {
  126. this.str1 = str1;
  127. this.str2 = '世界';
  128. }
  129. }
  130. @Entry
  131. @Component
  132. struct AddLog {
  133. @State logTrack: LogTrack = new LogTrack('Hello');
  134. @State logNotTrack: LogNotTrack = new LogNotTrack('你好');
  135. isRender(index: number) {
  136. console.log(`Text ${index} is rendered`);
  137. return 50;
  138. }
  139. build() {
  140. Row() {
  141. Column() {
  142. Text(this.logTrack.str1) // UINode1
  143. .fontSize(this.isRender(1))
  144. .fontWeight(FontWeight.Bold)
  145. Text(this.logTrack.str2) // UINode2
  146. .fontSize(this.isRender(2))
  147. .fontWeight(FontWeight.Bold)
  148. Button('change logTrack.str1')
  149. .onClick(() => {
  150. this.logTrack.str1 = 'Bye';
  151. })
  152. Text(this.logNotTrack.str1) // UINode3
  153. .fontSize(this.isRender(3))
  154. .fontWeight(FontWeight.Bold)
  155. Text(this.logNotTrack.str2) // UINode4
  156. .fontSize(this.isRender(4))
  157. .fontWeight(FontWeight.Bold)
  158. Button('change logNotTrack.str1')
  159. .onClick(() => {
  160. this.logNotTrack.str1 = '再见';
  161. })
  162. }
  163. .width('100%')
  164. }
  165. .height('100%')
  166. }
  167. }
  168. ```