if/else:條件渲染

2024-01-25 12:08 更新

ArkTS提供了渲染控制的能力。條件渲染可根據(jù)應(yīng)用的不同狀態(tài),使用if、else和else if渲染對應(yīng)狀態(tài)下的UI內(nèi)容。

說明

從API version 9開始,該接口支持在ArkTS卡片中使用。

使用規(guī)則

  • 支持if、else和else if語句。
  • if、else if后跟隨的條件語句可以使用狀態(tài)變量。
  • 允許在容器組件內(nèi)使用,通過條件渲染語句構(gòu)建不同的子組件。
  • 條件渲染語句在涉及到組件的父子關(guān)系時(shí)是“透明”的,當(dāng)父組件和子組件之間存在一個(gè)或多個(gè)if語句時(shí),必須遵守父組件關(guān)于子組件使用的規(guī)則。
  • 每個(gè)分支內(nèi)部的構(gòu)建函數(shù)必須遵循構(gòu)建函數(shù)的規(guī)則,并創(chuàng)建一個(gè)或多個(gè)組件。無法創(chuàng)建組件的空構(gòu)建函數(shù)會(huì)產(chǎn)生語法錯(cuò)誤。
  • 某些容器組件限制子組件的類型或數(shù)量,將條件渲染語句用于這些組件內(nèi)時(shí),這些限制將同樣應(yīng)用于條件渲染語句內(nèi)創(chuàng)建的組件。例如,Grid容器組件的子組件僅支持GridItem組件,在Grid內(nèi)使用條件渲染語句時(shí),條件渲染語句內(nèi)僅允許使用GridItem組件。

更新機(jī)制

當(dāng)if、else if后跟隨的狀態(tài)判斷中使用的狀態(tài)變量值變化時(shí),條件渲染語句會(huì)進(jìn)行更新,更新步驟如下:

  1. 評估if和else if的狀態(tài)判斷條件,如果分支沒有變化,無需執(zhí)行以下步驟。如果分支有變化,則執(zhí)行2、3步驟:
  2. 刪除此前構(gòu)建的所有子組件。
  3. 執(zhí)行新分支的構(gòu)造函數(shù),將獲取到的組件添加到if父容器中。如果缺少適用的else分支,則不構(gòu)建任何內(nèi)容。

條件可以包括Typescript表達(dá)式。對于構(gòu)造函數(shù)中的表達(dá)式,此類表達(dá)式不得更改應(yīng)用程序狀態(tài)。

使用場景

使用if進(jìn)行條件渲染

  1. @Entry
  2. @Component
  3. struct ViewA {
  4. @State count: number = 0;
  5. build() {
  6. Column() {
  7. Text(`count=${this.count}`)
  8. if (this.count > 0) {
  9. Text(`count is positive`)
  10. .fontColor(Color.Green)
  11. }
  12. Button('increase count')
  13. .onClick(() => {
  14. this.count++;
  15. })
  16. Button('decrease count')
  17. .onClick(() => {
  18. this.count--;
  19. })
  20. }
  21. }
  22. }

if語句的每個(gè)分支都包含一個(gè)構(gòu)建函數(shù)。此類構(gòu)建函數(shù)必須創(chuàng)建一個(gè)或多個(gè)子組件。在初始渲染時(shí),if語句會(huì)執(zhí)行構(gòu)建函數(shù),并將生成的子組件添加到其父組件中。

每當(dāng)if或else if條件語句中使用的狀態(tài)變量發(fā)生變化時(shí),條件語句都會(huì)更新并重新評估新的條件值。如果條件值評估發(fā)生了變化,這意味著需要構(gòu)建另一個(gè)條件分支。此時(shí)ArkUI框架將:

  1. 刪除所有以前渲染的(早期分支的)組件。
  2. 執(zhí)行新分支的構(gòu)造函數(shù),將生成的子組件添加到其父組件中。

在以上示例中,如果count從0增加到1,那么if語句更新,條件count > 0將重新評估,評估結(jié)果將從false更改為true。因此,將執(zhí)行條件為真分支的構(gòu)造函數(shù),創(chuàng)建一個(gè)Text組件,并將它添加到父組件Column中。如果后續(xù)count更改為0,則Text組件將從Column組件中刪除。由于沒有else分支,因此不會(huì)執(zhí)行新的構(gòu)造函數(shù)。

if ... else ...語句和子組件狀態(tài)

以下示例包含if ... else ...語句與擁有@State裝飾變量的子組件。

  1. @Component
  2. struct CounterView {
  3. @State counter: number = 0;
  4. label: string = 'unknown';
  5. build() {
  6. Row() {
  7. Text(`${this.label}`)
  8. Button(`counter ${this.counter} +1`)
  9. .onClick(() => {
  10. this.counter += 1;
  11. })
  12. }
  13. }
  14. }
  15. @Entry
  16. @Component
  17. struct MainView {
  18. @State toggle: boolean = true;
  19. build() {
  20. Column() {
  21. if (this.toggle) {
  22. CounterView({ label: 'CounterView #positive' })
  23. } else {
  24. CounterView({ label: 'CounterView #negative' })
  25. }
  26. Button(`toggle ${this.toggle}`)
  27. .onClick(() => {
  28. this.toggle = !this.toggle;
  29. })
  30. }
  31. }
  32. }

CounterView(label為 'CounterView #positive')子組件在初次渲染時(shí)創(chuàng)建。此子組件攜帶名為counter的狀態(tài)變量。當(dāng)修改CounterView.counter狀態(tài)變量時(shí),CounterView(label為 'CounterView #positive')子組件重新渲染時(shí)并保留狀態(tài)變量值。當(dāng)MainView.toggle狀態(tài)變量的值更改為false時(shí),MainView父組件內(nèi)的if語句將更新,隨后將刪除CounterView(label為 'CounterView #positive')子組件。與此同時(shí),將創(chuàng)建新的CounterView(label為 'CounterView #negative')實(shí)例。而它自己的counter狀態(tài)變量設(shè)置為初始值0。

說明

CounterView(label為 'CounterView #positive')和CounterView(label為 'CounterView #negative')是同一自定義組件的兩個(gè)不同實(shí)例。if分支的更改,不會(huì)更新現(xiàn)有子組件,也不會(huì)保留狀態(tài)。

以下示例展示了條件更改時(shí),若需要保留counter值所做的修改。

  1. @Component
  2. struct CounterView {
  3. @Link counter: number;
  4. label: string = 'unknown';
  5. build() {
  6. Row() {
  7. Text(`${this.label}`)
  8. Button(`counter ${this.counter} +1`)
  9. .onClick(() => {
  10. this.counter += 1;
  11. })
  12. }
  13. }
  14. }
  15. @Entry
  16. @Component
  17. struct MainView {
  18. @State toggle: boolean = true;
  19. @State counter: number = 0;
  20. build() {
  21. Column() {
  22. if (this.toggle) {
  23. CounterView({ counter: $counter, label: 'CounterView #positive' })
  24. } else {
  25. CounterView({ counter: $counter, label: 'CounterView #negative' })
  26. }
  27. Button(`toggle ${this.toggle}`)
  28. .onClick(() => {
  29. this.toggle = !this.toggle;
  30. })
  31. }
  32. }
  33. }

此處,@State counter變量歸父組件所有。因此,當(dāng)CounterView組件實(shí)例被刪除時(shí),該變量不會(huì)被銷毀。CounterView組件通過@Link裝飾器引用狀態(tài)。狀態(tài)必須從子級移動(dòng)到其父級(或父級的父級),以避免在條件內(nèi)容或重復(fù)內(nèi)容被銷毀時(shí)丟失狀態(tài)。

嵌套if語句

條件語句的嵌套對父組件的相關(guān)規(guī)則沒有影響。

  1. @Entry
  2. @Component
  3. struct CompA {
  4. @State toggle: boolean = false;
  5. @State toggleColor: boolean = false;
  6. build() {
  7. Column() {
  8. Text('Before')
  9. .fontSize(15)
  10. if (this.toggle) {
  11. Text('Top True, positive 1 top')
  12. .backgroundColor('#aaffaa').fontSize(20)
  13. // 內(nèi)部if語句
  14. if (this.toggleColor) {
  15. Text('Top True, Nested True, positive COLOR Nested ')
  16. .backgroundColor('#00aaaa').fontSize(15)
  17. } else {
  18. Text('Top True, Nested False, Negative COLOR Nested ')
  19. .backgroundColor('#aaaaff').fontSize(15)
  20. }
  21. } else {
  22. Text('Top false, negative top level').fontSize(20)
  23. .backgroundColor('#ffaaaa')
  24. if (this.toggleColor) {
  25. Text('positive COLOR Nested ')
  26. .backgroundColor('#00aaaa').fontSize(15)
  27. } else {
  28. Text('Negative COLOR Nested ')
  29. .backgroundColor('#aaaaff').fontSize(15)
  30. }
  31. }
  32. Text('After')
  33. .fontSize(15)
  34. Button('Toggle Outer')
  35. .onClick(() => {
  36. this.toggle = !this.toggle;
  37. })
  38. Button('Toggle Inner')
  39. .onClick(() => {
  40. this.toggleColor = !this.toggleColor;
  41. })
  42. }
  43. }
  44. }
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)