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

当应用中父子组件需要数据同步时,可以使用@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() // 一旦更改任务,就需要重新渲染  
      })  
   }  
}
  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值