小工具知识网

当前位置: 首页 > 行业知识 > HarmonyOS --@Prop和@Link同步信息装饰器

行业知识

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

2026-11-10 13:33:09 来源:互联网转载

当应���中父子组件需要数据同步时,可以使用@Prop和@Link装饰器

()

一个组件被引用时,引用其他组件的组件就是父组件、被引用的组件就是子组件。

由于@State装饰器无法执行父子之间的数据通信

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

Prop单向传递

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

@Component  struct TaskStatic {     @Prop finishTask: number  // Prop变量不需要初始化   @Prop totalTask: number       build() {        // ===任务数量显示卡片st===//        Row() {           Text('任务进度:') // 任务进度文字              .whiteFont()              .fontSize(30)              .fontWeight(FontWeight.Bold)             Stack() { // 叠加容器,容器内组件依次入栈,后一个组件覆盖前一个组件              // ===进度条st===//                        Progress({ value: this.finishTask, total: this.totalTask, type: ProgressType.Ring })                 .width(100)              // ===进度条end===//              Row() { // 两个文本,一个显示完成任务数量,一个显示总的任务数量                 Text(this.finishTask.toString()) // 完成任务                    .fontSize(24)                    .fontColor('#76D')                 Text(`/` + this.totalTask.toString()) // 所有任务                    .fontSize(24)                    .whiteFont()              }         }        }        .card()        .justifyContent(FlexAlign.SpaceEvenly)        // ===任务数量显示卡片end===//     }  }

入口代码:

@Entry  @Component  struct PropPage {     // 总的任务量     @State totalTask: number = 0     // 完成的任务     @State finishTask: number = 0       build() {        Column() {           // 标题栏st//           Header({ title: '任务统计案例' })           // 任务展示卡片组件  prop单向同步显示//           TaskStatic({ finishTask: this.finishTask, totalTask: this.totalTask })           // 任务列表组件//  TaskList({finishTask:$finishTask,totalTask:$totalTask})        }            .width('100%') // Column宽度        .height('100%') // Column高度        .backgroundColor('#F1F2F3')     }  }

Link变量初始化

语法:

@Component  struct TaskList {     @Link finishTask: number  // Link变量也不需要初始化   @Link totalTask: number     //任务数组     @State tasks: Task[] = []       handleTaskChange() {        this.totalTask = this.tasks.length // 所有的任务        // 遍历数组,过滤出已经完成的任务数量      this.finishTask = this.tasks.filter(item => item.finished).length     }       build() { // 子元素中必须只有一个根元素        Column() {           // ==新增任务按钮st==//           Button('新增任务')              .onClick(() => {                 // 1. 新增任务进入数组                 this.tasks.push(new Task())                 // 2. 改变任务总数                 this.handleTaskChange()              })              .width(100)              .height(40)              .type(ButtonType.Normal)              .borderRadius(15)              .margin(10)           // 新增任按钮end//             // 渲染列表st//                  List({ space: 10 }) {              ForEach(this.tasks, (item: Task, index) => {                 ListItem() {                    Row() {                       Text(`新增任务${index}`)                          .fontSize(24)                          .whiteFont()                       Checkbox({ name: 'checkbox' + index.toString() })                          .select(item.finished)                          .selectedColor(0xed6f21)                          .onChange((value: boolean) => {                             item.finished = value                             this.handleTaskChange()                          })                    }                    .card()                    .justifyContent(FlexAlign.SpaceBetween)                    .margin(6)                 }                 .swipeAction({ end: this.deleteButton(index) }) // 列表的右滑功能函数              })           }         .width('100%')           .layoutWeight(1) // 将剩下的空间全部给list元素           .alignListItem(ListItemAlign.Center) // 列表元素居中           // =渲染列表end=//               }     }       @Builder deleteButton(index: number) { // 删除按钮构建函数        Button() {           Image($r('app.media.delete'))              .width(40)              .padding(5)        }      .width(60)        .type(ButtonType.Circle)        .backgroundColor(Color.Brown)        .onClick(() => {           this.tasks.splice(index, 1) // 删除1个           this.handleTaskChange() // 一旦更改任务,就需要重新渲染        })     }  }
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,不需要初始化和传值。

import router from '@ohos.router'  import { Header } from '../components/herder'  // 创建Task类  class Task {     static id: number = 1     name: string = `任务${Task.id++}`     finished: boolean = false  }    // 创建单独的卡片样式  @Styles function card() {     .width('95%')     // .height(20)     .padding(20)     .backgroundColor(Color.Brown)     .borderRadius(15)     .shadow({ radius: 6, color: '#1F000000', offsetX: 2, offsetY: 4 })  }    // 任务完成样式  @Extend(Text) function finishedCard() {     .decoration({ type: TextDecorationType.LineThrough })     .fontColor('#B1B2B1')  }    // 任务白色字体  @Extend(Text) function whiteFont() {     .fontColor(Color.White)  }    @Entry  @Component  struct PropPage {     // 总的任务量     @Provide totalTask: number = 0     // 完成的任务     @Provide finishTask: number = 0       build() {        Column() {           // =======================标题栏st======================//           Header({ title: '任务统计案例' })           // =======================任务展示卡片组件======================//           TaskStatic()           // =======================任务列表组件======================//           TaskList()        }      .width('100%') // Column宽度        .height('100%') // Column高度        .backgroundColor('#F1F2F3')     }  }    @Component  struct TaskStatic {     @Consume finishTask: number     @Consume totalTask: number       build() {        // =======================任务数量显示卡片st======================//        Row() {           Text('任务进度:') // 任务进度文字              .whiteFont()              .fontSize(30)              .fontWeight(FontWeight.Bold)             Stack() { // 叠加容器,容器内组件依次入栈,后一个组件覆盖前一个组件              // =======================进度条st======================//            Progress({ value: this.finishTask, total: this.totalTask, type: ProgressType.Ring })                 .width(100)              // =======================进度条end======================//              Row() { // 两个文本,一个显示完成任务数量,一个显示总的任务数量                 Text(this.finishTask.toString()) // 完成任务                    .fontSize(24)                    .fontColor('#76D')                 Text(`/` + this.totalTask.toString()) // 所有任务                    .fontSize(24)                    .whiteFont()              }         }        }        .card()        .justifyContent(FlexAlign.SpaceEvenly)        // =======================任务数量显示卡片end======================//     }  }    @Component  struct TaskList {     @Consume finishTask: number     @Consume totalTask: number     //任务数组     @State tasks: Task[] = []       handleTaskChange() {        this.totalTask = this.tasks.length // 所有的任务        // 遍历数组,过滤出已经完成的任务数量      this.finishTask = this.tasks.filter(item => item.finished).length     }       build() { // 子元素中必须只有一个根元素        Column() {           // =======================新增任务按钮st======================//           Button('新增任务')              .onClick(() => {                 // 1. 新增任务进入数组                 this.tasks.push(new Task())                 // 2. 改变任务总数                 this.handleTaskChange()              })              .width(100)              .height(40)              .type(ButtonType.Normal)              .borderRadius(15)              .margin(10)           // =======================新增任按钮end======================//             // =======================渲染列表st======================//         List({ space: 10 }) {              ForEach(this.tasks, (item: Task, index) => {                 ListItem() {                    Row() {                       Text(`新增任务${index}`)                          .fontSize(24)                          .whiteFont()                       Checkbox({ name: 'checkbox' + index.toString() })                          .select(item.finished)                          .selectedColor(0xed6f21)                          .onChange((value: boolean) => {                             item.finished = value                             this.handleTaskChange()                          })                    }                    .card()                    .justifyContent(FlexAlign.SpaceBetween)                    .margin(6)                 }                 .swipeAction({ end: this.deleteButton(index) }) // 列表的右滑功能函数              })           }         .width('100%')           .layoutWeight(1) // 将剩下的空间全部给list元素           .alignListItem(ListItemAlign.Center) // 列表元素居中           // =======================渲染列表end======================//      }     }       @Builder deleteButton(index: number) { // 删除按钮构建函数        Button() {           Image($r('app.media.delete'))              .width(40)              .padding(5)        }      .width(60)        .type(ButtonType.Circle)        .backgroundColor(Color.Brown)        .onClick(() => {           this.tasks.splice(index, 1) // 删除1个           this.handleTaskChange() // 一旦更改任务,就需要重新渲染        })     }  }

上一篇:怎么表达太累异乡?

下一篇:揭秘游戏源码使用秘籍,轻松上手游戏开发之旅!