在 ArkUI 中、UI 表示の内容はすべてコンポーネントであり、フレームワークによって直接提供されるものはシステムコンポーネントと呼ばれ、開発者によって定義されるものはカスタムコンポーネントと呼ばれます。UI インターフェースの開発を行う際、通常はシステムコンポーネントを単純に組み合わせて使用するのではなく、コードの再利用性、ビジネスロジックと UI の分離、今後のバージョンの進化などの要素を考慮する必要があります。したがって、UI と一部のビジネスロジックをカスタムコンポーネントとしてカプセル化することは不可欠な能力です。
カスタムコンポーネント#
カスタムコンポーネントには以下の特徴があります:
- 組み合わせ可能:開発者がシステムコンポーネントおよびその属性やメソッドを組み合わせて使用することを許可します。
- 再利用可能:カスタムコンポーネントは他のコンポーネントで再利用でき、異なるインスタンスとして異なる親コンポーネントやコンテナで使用できます。
- データ駆動の UI 更新:状態変数の変更を通じて、UI の更新を駆動します。
カスタムコンポーネントの基本的な使い方#
@Component
struct HelloComponent {
@State message: string = 'Hello, World!';
build() {
// HelloComponentカスタムコンポーネントはシステムコンポーネントRowとTextを組み合わせます
Row() {
Text(this.message)
.onClick(() => {
// 状態変数messageの変更がUIの更新を駆動し、UIは'Hello, World!'から'Hello, ArkUI!'に更新されます
this.message = 'Hello, ArkUI!';
})
}
}
}
::: warning 注意
他のファイルでこのカスタムコンポーネントを参照する場合は、export キーワードを使用してエクスポートし、使用するページでこのカスタムコンポーネントをインポートする必要があります。
:::
HelloComponent は他のカスタムコンポーネントの build () 関数内で複数回作成され、カスタムコンポーネントの再利用を実現します。
class HelloComponentParam {
message: string = ""
}
@Entry
@Component
struct ParentComponent {
param: HelloComponentParam = {
message: 'Hello, World!'
}
build() {
Column() {
Text('ArkUI message')
HelloComponent(this.param);
Divider()
HelloComponent(this.param);
}
}
}
カスタムコンポーネントの基本構造#
- struct:カスタムコンポーネントは struct に基づいて実装され、struct + カスタムコンポーネント名 + {...} の組み合わせでカスタムコンポーネントを構成し、継承関係を持つことはできません。struct のインスタンス化では、new を省略できます。
::: tip 说明
カスタムコンポーネント名、クラス名、関数名はシステムコンポーネント名と同じであってはなりません。
:::
- @Component:@Component デコレーターは struct キーワードで宣言されたデータ構造のみを装飾できます。struct が @Component で装飾されると、コンポーネント化の能力を持ち、UI を記述する build メソッドを実装する必要があります。1 つの struct は 1 つの @Component でしか装飾できません。@Component はオプションの bool 型パラメータを受け取ることができます。
::: tip 说明
API バージョン 9 から、このデコレーターは ArkTS カードでの使用をサポートします。
API バージョン 11 から、@Component はオプションの bool 型パラメータを受け取ることができます。
:::
@Component
struct MyComponent {
}
freezeWhenInactive#
コンポーネントの凍結オプション。
@Component({ freezeWhenInactive: true })
struct MyComponent {
}
build () 関数#
build () 関数はカスタムコンポーネントの宣言的 UI 記述を定義するために使用され、カスタムコンポーネントは build () 関数を定義する必要があります。
@Component
struct MyComponent {
build() {
}
}
@Entry#
@Entry で装飾されたカスタムコンポーネントは UI ページのエントリとして機能します。単一の UI ページ内で、@Entry で装飾されたカスタムコンポーネントは最大 1 つまで使用できます。@Entry はオプションの LocalStorage パラメータを受け取ることができます。
::: tip 说明
API バージョン 9 から、このデコレーターは ArkTS カードでの使用をサポートします。
API バージョン 10 から、@Entry はオプションの LocalStorage パラメータまたはオプションの EntryOptions パラメータを受け取ることができます。
API バージョン 11 から、このデコレーターはメタサービスでの使用をサポートします。
:::
@Entry
@Component
struct MyComponent {
}```
EntryOptions10#
命名ルート遷移オプション。
@Entry({ routeName : 'myPage' })
@Component
struct MyComponent {
}
@Reusable:@Reusable で装飾されたカスタムコンポーネントは再利用可能な能力を持ちます
メンバー関数 / 変数#
- カスタムコンポーネントは build () 関数を実装する必要があるだけでなく、他のメンバー関数を実装することもできます。メンバー関数には以下の制約があります:
- カスタムコンポーネントのメンバー関数はプライベートであり、静的関数として宣言することは推奨されません。
- カスタムコンポーネントはメンバー変数を含むことができ、メンバー変数には以下の制約があります:
- カスタムコンポーネントのメンバー変数はプライベートであり、静的変数として宣言することは推奨されません。
- カスタムコンポーネントのメンバー変数のローカル初期化は一部がオプションであり、一部が必須です。具体的にローカル初期化が必要かどうか、親コンポーネントからパラメータを通じて子コンポーネントのメンバー変数を初期化する必要があるかどうかは、状態管理を参照してください。
カスタムコンポーネントのパラメータ規定#
上記の例から、build メソッド内でカスタムコンポーネントを作成できることがわかります。カスタムコンポーネントを作成する過程で、デコレーターのルールに従ってカスタムコンポーネントのパラメータを初期化します。
@Component
struct MyComponent {
private countDownFrom: number = 0;
private color: Color = Color.Blue;
build() {
}
}
@Entry
@Component
struct ParentComponent {
private someColor: Color = Color.Pink;
build() {
Column() {
// MyComponent インスタンスを作成し、MyComponent メンバー変数 countDownFrom を 10 で初期化し、メンバー変数 color を this.someColor で初期化します
MyComponent({ countDownFrom: 10, color: this.someColor })
}
}
}
build () 関数#
build () 関数内で宣言されたすべての文は、UI 記述と呼ばれ、UI 記述は以下のルールに従う必要があります:
- @Entry で装飾されたカスタムコンポーネントは、その build () 関数の下のルートノードが一意であり、必要であり、コンテナコンポーネントでなければならず、ForEach はルートノードとして禁止されています。
- @Component で装飾されたカスタムコンポーネントは、その build () 関数の下のルートノードが一意であり、必要であり、非コンテナコンポーネントであってもよく、ForEach はルートノードとして禁止されています。
@Entry
@Component
struct MyComponent {
build() {
// ルートノードは一意であり、必要であり、コンテナコンポーネントでなければなりません
Row() {
ChildComponent()
}
}
}
@Component
struct ChildComponent {
build() {
// ルートノードは一意であり、必要であり、非コンテナコンポーネントであってもよい
Image('test.jpg')
}
}
- ローカル変数を宣言することは許可されていません。以下は反例です。
build() {
// 反例:ローカル変数を宣言することは許可されていません
let a: number = 1;
}
- UI 記述内で直接 console.info を使用することは許可されていませんが、メソッドや関数内で使用することは許可されています。以下は反例です。
build() {
// 反例:console.info を使用することは許可されていません
console.info('print debug log');
}
- @Builder デコレーターを使用していないメソッドを呼び出すことは許可されていませんが、システムコンポーネントのパラメータは TS メソッドの戻り値であることが許可されています。
@Component
struct ParentComponent {
doSomeCalculations() {
}
calcTextValue(): string {
return 'Hello World';
}
@Builder doSomeRender() {
Text(`Hello World`)
}
build() {
Column() {
// 反例:@Builder デコレーターを使用していないメソッドを呼び出すことはできません
this.doSomeCalculations();
// 正例:呼び出すことができます
this.doSomeRender();
// 正例:パラメータは TS メソッドの戻り値であることができます
Text(this.calcTextValue())
}
}
}
- switch 構文を使用することは許可されていません。条件判断が必要な場合は、if を使用してください。以下は例です。
build() {
Column() {
// 反例:switch 構文を使用することは許可されていません
switch (expression) {
case 1:
Text('...')
break;
case 2:
Image('...')
break;
default:
Text('...')
break;
}
// 正例:if を使用します
if(expression == 1) {
Text('...')
} else if(expression == 2) {
Image('...')
} else {
Text('...')
}
}
}
- 状態変数を直接変更することは許可されていません。以下は反例です。詳細な分析は @State のよくある質問を参照してください:build 内で状態変数を変更することは許可されていません。
@Component
struct CompA {
@State col1: Color = Color.Yellow;
@State col2: Color = Color.Green;
@State count: number = 1;
build() {
Column() {
// Text コンポーネント内で count の値を直接変更することは避けるべきです
Text(`${this.count++}`)
.width(50)
.height(50)
.fontColor(this.col1)
.onClick(() => {
this.col2 = Color.Red;
})
Button("change col1").onClick(() =>{
this.col1 = Color.Pink;
})
}
.backgroundColor(this.col2)
}
}
ArkUI の状態管理では、状態が UI 更新を駆動します。
したがって、カスタムコンポーネントの build () または @Builder メソッド内で状態変数を直接変更することはできません。これにより、循環レンダリングのリスクが生じる可能性があります。Text ('${this.count++}') は全体更新または最小化更新で異なる影響を与えます:
-
全体更新(API8 および以前のバージョン):ArkUI は無限の再レンダリングループに陥る可能性があります。なぜなら、Text コンポーネントの各レンダリングはアプリケーションの状態を変更し、次のレンダリングを引き起こすからです。 this.col2 が変更されると、全体の build 構築関数が実行され、
Text(${this.count++})
にバインドされたテキストも変更されます。再レンダリングのたびにText(${this.count++})
が再描画され、this.count 状態変数が更新され、新たな build が実行され、無限ループに陥ります。 -
最小化更新(API9 から現在のバージョン): this.col2 が変更されると、Column コンポーネントのみが更新され、Text コンポーネントは変更されません。 this.col1 が変更されると、全体の Text コンポーネントが更新され、そのすべての属性関数が実行されるため、
Text(${this.count++})
が自増します。現在、UI はコンポーネント単位で更新されているため、コンポーネント上の特定の属性が変更されると、全体のコンポーネントが更新されます。したがって、全体の更新の流れは:this.col1 = Color.Pink -> Text コンポーネント全体が更新 -> this.count++ -> Text コンポーネント全体が更新です。この書き方は初回レンダリング時に Text コンポーネントが 2 回レンダリングされるため、パフォーマンスに影響を与えることに注意が必要です。
build 関数内でアプリケーションの状態を変更する行為は、上記の例よりもさらに隠蔽される可能性があります。例えば:
- @Builder、@Extend または @Styles メソッド内で状態変数を変更すること。
- パラメータを計算する際に関数内でアプリケーションの状態変数を変更すること、例えば
Text('${this.calcLabel()}')
。 - 現在の配列を変更し、sort () が配列 this.arr を変更し、その後の filter メソッドが新しい配列を返すこと。
カスタムコンポーネントの共通スタイル#
カスタムコンポーネントは「.」のチェーン呼び出し形式で共通スタイルを設定します。
@Component
struct MyComponent2 {
build() {
Button(`Hello World`)
}
}
@Entry
@Component
struct MyComponent {
build() {
Row() {
MyComponent2()
.width(200)
.height(300)
.backgroundColor(Color.Red)
}
}
}
::: tip 说明
ArkUI がカスタムコンポーネントにスタイルを設定する際、MyComponent2 に不可視のコンテナコンポーネントを設定することに相当します。これらのスタイルはコンテナコンポーネントに設定されており、MyComponent2 の Button コンポーネントに直接設定されるわけではありません。レンダリング結果から、背景色の赤は Button に直接適用されず、Button が存在する開発者には見えないコンテナコンポーネントに適用されていることが明確にわかります。
:::
この文は Mix Space によって xLog に同期更新されました
元のリンクは http://www.sroxck.top/posts/harmony/arkts-components