HarmonyOS-基礎之元件資料傳遞

我也有梦想呀發表於2024-04-05

1、父傳子@State和@Prop

父元件
// 匯入子元件
import Child01 from '../components/Child01'

@Entry
@Component
struct StateExample {
  @State count: number = 0
  build() {
    Column() {
      Text("計數器 count:" + this.count)
      Button('count + 1').onClick(() => {
        // 這裡使用 this.count++ 會有問題
        this.count += 1
      })
      Child01({ a: this.count }).margin({ top: 10 })
    }.width('100%')
    .height(300)
  }
}
子元件
@Component
export default struct Child01 {
  // 使用@Prop定義父傳子資料,資料單向流動
  @Prop a: number;
  build() {
    Column() {
      Text('我是子元件Child1')
      Text('父元件傳遞的count:  ' + this.a)
      Button('修改父元件count資料').onClick(() => {
        this.a -= 1
      }).margin({bottom:5})
    }.width('100%').border({ width: 1, color: Color.Black })
  }
}

注意:使用@State和@Prop進行父子元件資料通訊時,資料流是單向的;父元件修改count子元件可以動態更新,而子元件無法修改父元件的資料

2、父子通訊@Link($state屬性)

父元件
// 匯入子元件
import Child02 from '../components/Child02'

@Entry
@Component
struct StateExample {
  @State count1: number = 199

  build() {
    Column() {
      Text("計數器 count1:" + this.count1)
      Button('count1 + 1').onClick(() => {
        // 這裡使用 this.count++ 會有問題
        this.count1 += 1
      }).margin({ top: 5 })
      Child02({ b: $count1 }).margin({ top: 10 })
    }.width('100%')
    .height(300)
  }
}
子元件
@Component
export default struct Child02 {
  // @Link 實現父子元件的雙向流動
  @Link b:number ;
  build() {
    Column({space:10}){
      Text('我是子元件Child2')
      Text('父元件傳遞過來的count1:  '+this.b)
      Button('修改父元件count1資料').onClick(() => {
        this.b -= 1
      }).margin({bottom:5})
    }.width('100%')
    .border({width:1,color:Color.Pink})
  }
}

image

注意:此方式父子資料傳遞,資料流是雙向的;父修改資料子跟這邊,同理子修改資料父也跟著變

3、父子通訊@Provide和@Consume

顧名思義:提供資料,消費資料

父元件
// 匯入子元件
import Child03 from '../components/Child03'

@Entry
@Component
struct StateExample {
  @Provide money: number = 10000000

  build() {
    Column() {
      Text("父元件的錢數 money:" + this.money)
      Button('money + 3').onClick(() => {
        // 這裡使用 this.count++ 會有問題
        this.money += 3
      }).margin({ top: 5 })
      Child03().margin({top:10})
    }.width('100%')
    .height(300)
  }
}
子元件
@Component
export default struct Child03 {
  @Consume money:number;
  build() {
    Column() {
      Text(`孫子元件有的money:${this.money}`)
      Button('修改money').onClick(() => {
        this.money -=1
      }).margin({top:10,bottom:10})
    }
    .width('100%')
    .border({ width: 1, color: Color.Pink })
  }
}

注意:此方式祖孫資料傳遞,資料流是雙向的;和@Link很像,但是它可以實現祖孫之間的資料雙向流動

4、元件傳遞引用資料型別-物件

父元件

@Component
export default struct Child04 {
  /**
   * he '@Prop' decorated attribute 'obj' must be of the string, number, or boolean type. <etsLint>
   * 官方建議:@Prop不要傳遞引用型別,但是如果你非要傳遞也沒問題
   */
  @Prop obj: {
    a: number,
    b: { c: number }
  }

  build() {
    Column() {
      Text('子元件Child04')
      Text('獲取父元件傳遞的複雜型別:\r\n' + JSON.stringify(this.obj))
      Button('修改父元件obj').onClick(() => {
        // this.obj.a = 99 // 監聽到,資料單向傳遞
        this.obj.b = { c: 101 } // 監聽到
        // this.obj.b.c = -1 // 超過一層,無法監聽

      })
    }.width('100%')
    .border({ width: 1, color: Color.Red })
  }
}

子元件

@Component
export default struct Child04 {
  @Prop obj: {
    a: number,
    b: { c: number }
  }
  build() {
    Column() {
      Text('子元件Child04')
      Text('獲取父元件傳遞的複雜型別:\r\n' + JSON.stringify(this.obj))
      Button('修改父元件obj').onClick(() => {
        // this.obj.a = 99 // 監聽到,資料單向傳遞
        // this.obj.b = { c: 101 } // 監聽到
        this.obj.b.c = -1 // 超過一層,無法監聽

      })
    }.width('100%')
    .border({ width: 1, color: Color.Red })
  }
}

5、元件傳遞引用資料型別-陣列

父元件

import Child04 from '../components/Child04'
import Child05 from '../components/Child05'
import Child06 from '../components/Child06'

@Entry
@Component
struct CompoundExample {

  // @State定義複雜型別
  @State obj: {
    a: number,
    b: { c: number }
  } = { a: 100, b: { c: 200 } }

  // 陣列型別
  @State arr: [{
    a: number,
    b: { c: number }
  }] = [{ a: 11, b: { c: 22 } }]

  build() {
    Column() {
      Text('父元件的複雜型別:\r\n' + JSON.stringify(this.obj)).fontSize(15)
      Button('修改obj').onClick(() => {
        // this.obj = {a:99,b:{c:19}} // 監聽到
        // this.obj.a = 199 // 監聽到
        this.obj.b = { c: 111 } // 監聽到
        // this.obj.b.c = 21 // 超過一層則無法監聽到
      })
      Child04({ obj: this.obj })
      // 透過@Link方式傳遞
      Child05({ obj: $obj }).margin({ top: 10 })
      // 陣列型別傳遞
      // Child06({ arr: this.arr })
      Child06({ arr: $arr })
    }.width('100%')
    .border({ width: 1, color: Color.Pink })
  }
}

子元件

@Component
export default struct Child06 {
  // @Prop arr: [{
  //   a: number,
  //   b: { c: number }
  // }]

  @Link arr: [{
    a: number,
    b: { c: number }
  }]

  build() {
    Column() {
      Text('子元件Child06透過@Link獲取父元件傳遞的複雜型別arr:' + JSON.stringify(this.arr))
      Button('修改父元件arr').onClick((event: ClickEvent) => {
        // 替換
        // this.arr = [{ a: 101, b: { c: 202 } }]
        // 修改
        this.arr[0].a = 909 // 無效的
      })
    }.width('100%')
    .border({ width: 1, color: Color.Blue })
  }
}

image

相關文章