赞
踩
当应用中父子组件需要数据同步时,可以使用@Prop和@Link装饰器
一个组件被引用时,引用其他组件的组件就是父组件、被引用的组件就是子组件。
由于@State装饰器无法执行父子之间的数据通信
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() // 一旦更改任务,就需要重新渲染
- })
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。