HarmonyOS-基礎之@Watch監聽、@ObjectLink和@Observed

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

1、Watch監聽

類似Vue中的資料監聽,監聽的資料發生了變化 --> 做啥事情

父元件

import Child07 from '../components/Child07'

@Entry
@Component
struct WatchExample {
  // watch 可以監聽元件狀態 State | Link | Provide ......
  @State @Watch('update') obj: {
    a: number,
    b: { c: number }
  } = { a: 123, b: { c: 456 } }

  // watch的監聽回撥
  update() {
    console.log('監聽到obj的變化')
  }

  build() {
    Column() {
      Text('watch監聽').fontSize(20)
      // 子元件
      // Child07({ obj: this.obj })
      Child07({obj:$obj})
    }.width("100%")
  }
}

子元件

@Component
export default struct Child07 {
  // Prop好像監測不到
  // @Prop obj: {
  //   a: number,
  //   b: { c: number }
  // }

  @Link obj: {
    a: number,
    b: { c: number }
  }

  build() {
    Column() {
      Text('子元件Child07獲取父元件傳遞的資料obj:' + JSON.stringify(this.obj))
      Button('修改父元件@Watch監聽的資料').onClick((event: ClickEvent) => {
        // this.obj = { a: 20, b: { c: 30 } }
        this.obj.a += 100
        // 無法深度監聽
        // this.obj.b.c += 9
      })
    }
    .width('100%')
    .border({ width: 1, color: Color.White })
  }
}

image

注意:@Watch是淺監聽,上面的案例也可以看出;至於深度監聽的寫法後面會演示

2、ObjectLink和Observed

從前面的Watch可以看出物件中的物件或者陣列中的物件屬性等深層次的屬性變化時UI無法更新;所以ObjectLink和Observed就可以來解決這個問題了;
案例如下:

Person物件

@Observed
export class Person {
  id: number
  name: string
  age: number

  constructor(id: number, name: string, age: number) {
    this.id = id
    this.name = name
    this.age = age
  }
}

父元件

import { Person } from '../domain/Model'
import Item01 from '../components/Item01'

@Entry
@Component
struct ObjectLinkExample {
  @State userArr: Person[] = [new Person(1, 'zs', 19), new Person(2, 'ls', 23)]

  build() {
    Column() {
      Text(JSON.stringify(this.userArr)).onClick(() => {
        console.log(JSON.stringify(this.userArr))
      })
      Button('更新資料').onClick((event: ClickEvent) => {
        this.userArr[0].age += 1
      })
      ForEach(this.userArr, (item: Person, index: number) => {
        Item01({ item: item })
      })
    }.width('100%')
  }
}

子元件

import { Person } from '../domain/Model'

@Component
export default struct Item01 {
  @ObjectLink item: Person

  build() {
    Column() {
      Text('Item01子元件,透過@Observed和@ObjectLink獲取到父元件傳遞的資料:' + JSON.stringify(this.item))
      Button('更新資料').onClick((event: ClickEvent) => {
        this.item.age += 1
      })
    }.width('100%')
    .padding(20)
    .border({ width: 1, color: Color.Red })
  }
}

image

image

相關文章