当前位置:   article > 正文

HarmonyOS --@Prop和@Link同步信息装饰器_harmonyos @prop

harmonyos @prop

当应用中父子组件需要数据同步时,可以使用@Prop和@Link装饰器
一个组件被引用时,引用其他组件的组件就是父组件、被引用的组件就是子组件。
由于@State装饰器无法执行父子之间的数据通信

  1. @Prop:单向同步、父组件中修改数据,会同步到子组件,但是子组件修改数据,父组件中不会同步,底层实现的是传递的父组件中的变量的拷贝。
  2. @Link:双向同步、修改父子组件中的数据,修改会同步到父子组件中,底层实现的是传递的父子组件中的变量的引用。

Prop单向传递

语法: 将一个显示任务数量和完成情况的卡片组件进行封装

  1. @Component
  2. struct TaskStatic {
  3. @Prop finishTask: number // Prop变量不需要初始化
  4. @Prop totalTask: number
  5. build() {
  6. // ===任务数量显示卡片st===//
  7. Row() {
  8. Text('任务进度:') // 任务进度文字
  9. .whiteFont()
  10. .fontSize(30)
  11. .fontWeight(FontWeight.Bold)
  12. Stack() { // 叠加容器,容器内组件依次入栈,后一个组件覆盖前一个组件
  13. // ===进度条st===//
  14. Progress({ value: this.finishTask, total: this.totalTask, type: ProgressType.Ring })
  15. .width(100)
  16. // ===进度条end===//
  17. Row() { // 两个文本,一个显示完成任务数量,一个显示总的任务数量
  18. Text(this.finishTask.toString()) // 完成任务
  19. .fontSize(24)
  20. .fontColor('#76D')
  21. Text(`/` + this.totalTask.toString()) // 所有任务
  22. .fontSize(24)
  23. .whiteFont()
  24. }
  25. }
  26. }
  27. .card()
  28. .justifyContent(FlexAlign.SpaceEvenly)
  29. // ===任务数量显示卡片end===//
  30. }
  31. }

入口代码:

  1. @Entry
  2. @Component
  3. struct PropPage {
  4. // 总的任务量
  5. @State totalTask: number = 0
  6. // 完成的任务
  7. @State finishTask: number = 0
  8. build() {
  9. Column() {
  10. // 标题栏st//
  11. Header({ title: '任务统计案例' })
  12. // 任务展示卡片组件 prop单向同步显示//
  13. TaskStatic({ finishTask: this.finishTask, totalTask: this.totalTask })
  14. // 任务列表组件//
  15. TaskList({finishTask:$finishTask,totalTask:$totalTask})
  16. }
  17. .width('100%') // Column宽度
  18. .height('100%') // Column高度
  19. .backgroundColor('#F1F2F3')
  20. }
  21. }

Link变量初始化

语法:

  1. @Component
  2. struct TaskList {
  3. @Link finishTask: number // Link变量也不需要初始化
  4. @Link totalTask: number
  5. //任务数组
  6. @State tasks: Task[] = []
  7. handleTaskChange() {
  8. this.totalTask = this.tasks.length // 所有的任务
  9. // 遍历数组,过滤出已经完成的任务数量 this.finishTask = this.tasks.filter(item => item.finished).length
  10. }
  11. build() { // 子元素中必须只有一个根元素
  12. Column() {
  13. // ==新增任务按钮st==//
  14. Button('新增任务')
  15. .onClick(() => {
  16. // 1. 新增任务进入数组
  17. this.tasks.push(new Task())
  18. // 2. 改变任务总数
  19. this.handleTaskChange()
  20. })
  21. .width(100)
  22. .height(40)
  23. .type(ButtonType.Normal)
  24. .borderRadius(15)
  25. .margin(10)
  26. // 新增任按钮end//
  27. // 渲染列表st//
  28. List({ space: 10 }) {
  29. ForEach(this.tasks, (item: Task, index) => {
  30. ListItem() {
  31. Row() {
  32. Text(`新增任务${index}`)
  33. .fontSize(24)
  34. .whiteFont()
  35. Checkbox({ name: 'checkbox' + index.toString() })
  36. .select(item.finished)
  37. .selectedColor(0xed6f21)
  38. .onChange((value: boolean) => {
  39. item.finished = value
  40. this.handleTaskChange()
  41. })
  42. }
  43. .card()
  44. .justifyContent(FlexAlign.SpaceBetween)
  45. .margin(6)
  46. }
  47. .swipeAction({ end: this.deleteButton(index) }) // 列表的右滑功能函数
  48. })
  49. } .width('100%')
  50. .layoutWeight(1) // 将剩下的空间全部给list元素
  51. .alignListItem(ListItemAlign.Center) // 列表元素居中
  52. // =渲染列表end=//
  53. }
  54. }
  55. @Builder deleteButton(index: number) { // 删除按钮构建函数
  56. Button() {
  57. Image($r('app.media.delete'))
  58. .width(40)
  59. .padding(5)
  60. } .width(60)
  61. .type(ButtonType.Circle)
  62. .backgroundColor(Color.Brown)
  63. .onClick(() => {
  64. this.tasks.splice(index, 1) // 删除1个
  65. this.handleTaskChange() // 一旦更改任务,就需要重新渲染
  66. })
  67. }
  68. }
TaskList({finishTask:$finishTask,totalTask:$totalTask})}


传值的时候需要传变量的引用:$+变量名

总结

父组件影响子组件用Prop,父子组件相互影响需要用Link,互不影响使用State

其次,允许装饰的变量类型也不一样,Prop只支持string、number、boolean、enum类型,父组件对象类型,子组件是对象属性。不可以是数组、any类型。

而Link,父子类型一致,string、number、boolean、enum、object、class,以及他们的数组。数组中元素增删、替换都会引起刷新。嵌套类型以及数组中的对象属性无法触发视图更新。

初始化方式上看,Prop不允许子组件初始化,Link由父组件传递,禁止子组件初始化。

也提供了另一种传递方式,@Provide 和@Consume,不需要初始化和传值。

  1. import router from '@ohos.router'
  2. import { Header } from '../components/herder'
  3. // 创建Task类
  4. class Task {
  5. static id: number = 1
  6. name: string = `任务${Task.id++}`
  7. finished: boolean = false
  8. }
  9. // 创建单独的卡片样式
  10. @Styles function card() {
  11. .width('95%')
  12. // .height(20)
  13. .padding(20)
  14. .backgroundColor(Color.Brown)
  15. .borderRadius(15)
  16. .shadow({ radius: 6, color: '#1F000000', offsetX: 2, offsetY: 4 })
  17. }
  18. // 任务完成样式
  19. @Extend(Text) function finishedCard() {
  20. .decoration({ type: TextDecorationType.LineThrough })
  21. .fontColor('#B1B2B1')
  22. }
  23. // 任务白色字体
  24. @Extend(Text) function whiteFont() {
  25. .fontColor(Color.White)
  26. }
  27. @Entry
  28. @Component
  29. struct PropPage {
  30. // 总的任务量
  31. @Provide totalTask: number = 0
  32. // 完成的任务
  33. @Provide finishTask: number = 0
  34. build() {
  35. Column() {
  36. // =======================标题栏st======================//
  37. Header({ title: '任务统计案例' })
  38. // =======================任务展示卡片组件======================//
  39. TaskStatic()
  40. // =======================任务列表组件======================//
  41. TaskList()
  42. } .width('100%') // Column宽度
  43. .height('100%') // Column高度
  44. .backgroundColor('#F1F2F3')
  45. }
  46. }
  47. @Component
  48. struct TaskStatic {
  49. @Consume finishTask: number
  50. @Consume totalTask: number
  51. build() {
  52. // =======================任务数量显示卡片st======================//
  53. Row() {
  54. Text('任务进度:') // 任务进度文字
  55. .whiteFont()
  56. .fontSize(30)
  57. .fontWeight(FontWeight.Bold)
  58. Stack() { // 叠加容器,容器内组件依次入栈,后一个组件覆盖前一个组件
  59. // =======================进度条st======================// Progress({ value: this.finishTask, total: this.totalTask, type: ProgressType.Ring })
  60. .width(100)
  61. // =======================进度条end======================//
  62. Row() { // 两个文本,一个显示完成任务数量,一个显示总的任务数量
  63. Text(this.finishTask.toString()) // 完成任务
  64. .fontSize(24)
  65. .fontColor('#76D')
  66. Text(`/` + this.totalTask.toString()) // 所有任务
  67. .fontSize(24)
  68. .whiteFont()
  69. } }
  70. }
  71. .card()
  72. .justifyContent(FlexAlign.SpaceEvenly)
  73. // =======================任务数量显示卡片end======================//
  74. }
  75. }
  76. @Component
  77. struct TaskList {
  78. @Consume finishTask: number
  79. @Consume totalTask: number
  80. //任务数组
  81. @State tasks: Task[] = []
  82. handleTaskChange() {
  83. this.totalTask = this.tasks.length // 所有的任务
  84. // 遍历数组,过滤出已经完成的任务数量 this.finishTask = this.tasks.filter(item => item.finished).length
  85. }
  86. build() { // 子元素中必须只有一个根元素
  87. Column() {
  88. // =======================新增任务按钮st======================//
  89. Button('新增任务')
  90. .onClick(() => {
  91. // 1. 新增任务进入数组
  92. this.tasks.push(new Task())
  93. // 2. 改变任务总数
  94. this.handleTaskChange()
  95. })
  96. .width(100)
  97. .height(40)
  98. .type(ButtonType.Normal)
  99. .borderRadius(15)
  100. .margin(10)
  101. // =======================新增任按钮end======================//
  102. // =======================渲染列表st======================// List({ space: 10 }) {
  103. ForEach(this.tasks, (item: Task, index) => {
  104. ListItem() {
  105. Row() {
  106. Text(`新增任务${index}`)
  107. .fontSize(24)
  108. .whiteFont()
  109. Checkbox({ name: 'checkbox' + index.toString() })
  110. .select(item.finished)
  111. .selectedColor(0xed6f21)
  112. .onChange((value: boolean) => {
  113. item.finished = value
  114. this.handleTaskChange()
  115. })
  116. }
  117. .card()
  118. .justifyContent(FlexAlign.SpaceBetween)
  119. .margin(6)
  120. }
  121. .swipeAction({ end: this.deleteButton(index) }) // 列表的右滑功能函数
  122. })
  123. } .width('100%')
  124. .layoutWeight(1) // 将剩下的空间全部给list元素
  125. .alignListItem(ListItemAlign.Center) // 列表元素居中
  126. // =======================渲染列表end======================// }
  127. }
  128. @Builder deleteButton(index: number) { // 删除按钮构建函数
  129. Button() {
  130. Image($r('app.media.delete'))
  131. .width(40)
  132. .padding(5)
  133. } .width(60)
  134. .type(ButtonType.Circle)
  135. .backgroundColor(Color.Brown)
  136. .onClick(() => {
  137. this.tasks.splice(index, 1) // 删除1个
  138. this.handleTaskChange() // 一旦更改任务,就需要重新渲染
  139. })
  140. }
  141. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/288928
推荐阅读
相关标签
  

闽ICP备14008679号