ArkTSデコレータの活用方法

UI状態管理

@Entry (エントリーポイント)

ページには一つだけ@Entryが存在します。

@Entry
@Component
struct IndexPage {
  @State userDetail: string = ''
  
  aboutToAppear() {
    console.info('IndexPage 即将显示')
    
    // サンプル1:AppStorageからデータ取得
    this.userDetail = AppStorage.get<string>('userName', '匿名ユーザー')

    // サンプル2:ネットワークリクエストのシミュレーション
    this.loadUserData()

    // サンプル3:埋点統計
    analyticsService.pageView('HomePage')
  }

  async loadUserData() {
    try {
      const data = await fetchUserApi()
      console.info('ユーザーデータ読み込み完了:', data)
      this.userDetail = data.name
    } catch (error) {
      console.error('読み込み失敗:', error)
    }
  }

  build() {
    Column() {
      Text(`ユーザー:${this.userDetail}`)
        .fontSize(18)
        .margin(20)
    }
    .width('100%')
    .height('100%')
  }
}

@Component (コンポーネント)

HarmonyOSのライフサイクルは、@Componentと@Entryで分類されます。それぞれカスタムコンポーネントとページのライフサイクルを指します。

コンポーネントの特徴:
  1. ページには一つだけ@Entryがあります。
  2. ページは複数のコンポーネントを含むことができます。
  3. 各コンポーネントはbuildメソッドを持ち、UIを更新する必要があります。
  4. コンポーネント内部で他のコンポーネントを呼び出すことができます。

@Builder (ビルド関数)

1. 引数なしの@Builder
@Builder
function simpleTextBuilder() {
  Text('こんにちは世界')
    .fontSize(30)
    .fontWeight(FontWeight.Bold)
    .fontColor(Color.Blue)
}
2. 引数付きの@Builder
@Builder
function paramTextBuilder(text: string, size: number, color: Color) {
  Text(text)
    .fontSize(size)
    .fontColor(color)
    .fontWeight(FontWeight.Medium)
}
3. 条件付きの@Builder
@Builder
function conditionalTextBuilder(score: number) {
  if (score >= 90) {
    Text('優秀')
      .fontColor(Color.Green)
  } else if (score >= 60) {
    Text('合格')
      .fontColor(Color.Orange)
  } else {
    Text('不合格')
      .fontColor(Color.Red)
  }
}
4. ループ付きの@Builder
@Builder
function listTextBuilder(items: string[]) {
  Column() {
    ForEach(items, (item: string) => {
      Text(item)
        .fontSize(16)
        .margin(5)
    })
  }
}

@State (ステート)

@Stateで修飾された変数は、UIレンダリングと結びつきます。状態が変化すると、UIも対応して更新されます。

@Entry
@Component
struct CounterExample {
  @State count: number = 0

  build() {
    Column({ space: 20 }) {
      Text(`現在のカウント: ${this.count}`)
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
        .fontColor(Color.Blue)

      Button('カウントアップ +1')
        .onClick(() => {
          this.count++
        })
        .width(200)
        .height(50)
        .backgroundColor(Color.Green)

      Button('カウントダウン -1')
        .onClick(() => {
          this.count--
        })
        .width(200)
        .height(50)
        .backgroundColor(Color.Orange)

      Button('リセット')
        .onClick(() => {
          this.count = 0
        })
        .width(200)
        .height(50)
        .backgroundColor(Color.Red)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Prop (プロパティ)

単方向データフロー:親コンポーネントから子コンポーネントへデータが流れます。子コンポーネントは親コンポーネントのデータを直接変更できません。

// 簡単な型
@Prop itemCount: number;
// 複雑な型
@Prop title: Model;

class Info {
  value: string;
  constructor(value: string) {
    this.value = value;
  }
}

class Model {
  value: string;
  info: Info;
  constructor(value: string, info: Info) {
    this.value = value;
    this.info = info;
  }
}

@Prop bookModel: Model;
// 第一層の変更は観測可能
this.bookModel.value = '新しいタイトル';
// 第二層の変更は観測不可
this.bookModel.info.value = '新しい情報';

@Link (双方向バインディング)

双方向データバインディングにより、親子コンポーネント間でデータが同期されます。

@Entry
@Component
struct ParentComponent {
  @State parentMessage: string = "Hello from Parent"

  build() {
    Column({ space: 20 }) {
      Text("親コンポーネントのメッセージ")
        .fontSize(18)
        .text(this.parentMessage)

      Button('親コンポーネントのメッセージを変更')
        .onClick(() => {
          this.parentMessage = "親コンポーネントのメッセージが更新されました"
        })
        .width(200)

      ChildComponent({
        message: $parentMessage
      })
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .justifyContent(FlexAlign.Center)
  }
}

@Component
struct ChildComponent {
  @Link message: string

  build() {
    Column({ space: 15 }) {
      Text(`親コンポーネントからのメッセージ: ${this.message}`)

      Button('メッセージをローカルに変更')
        .onClick(() => {
          this.message += " (ローカル変更)"
        })
        .width(200)
    }
    .padding(15)
    .border({ width: 1, color: Color.Gray })
    .borderRadius(10)
    .margin({ top: 20 })
  }
}

@Provide / @Consume (データ提供と消費)

@Provideと@Consumeは、多階層の親子コンポーネント間でデータを効率的に伝達するために使用されます。

@Entry
@Component
struct ParentComponent {
  @Provide globalCount: number = 0

  build() {
    Column() {
      Text(`グローバルカウント: ${this.globalCount}`)
        .onClick(() => {
          this.globalCount++
        })

      ChildComponent()
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

@Component
struct ChildComponent {
  @Consume globalCount: number

  build() {
    Column() {
      Text(`受け取ったグローバルカウント: ${this.globalCount}`)
        .onClick(() => {
          this.globalCount++
        })
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

タグ: AkTS UI管理 コンポーネント ライフサイクル デコレータ

6月28日 18:03 投稿