HarmonyOS/OpenHarmony application development-ArkTS language rendering control if/else conditional rendering

ArkTS provides rendering control capabilities. Conditional rendering can use if, else and else if to render the UI content in the corresponding state according to the different states of the application. Note: Starting from API version 9, this interface supports use in ArkTS cards.
1. Usage rules
Support if, else and else if statements.
The conditional statements following if and else if can use state variables.
Allows use within container components to build different sub-components through conditional rendering statements.
Conditional rendering statements are "transparent" when it comes to the parent-child relationship of a component. When one or more if statements exist between a parent component and a child component, the rules of the parent component regarding the use of child components must be followed.
The build function inside each branch must follow the rules of the build function and create one or more components. An empty constructor that cannot create a component produces a syntax error.
Some container components limit the type or number of child components. When conditional rendering statements are used within these components, these restrictions will also apply to components created within the conditional rendering statements. For example, the subcomponents of the Grid container component only support the GridItem component. When using conditional rendering statements within the Grid, only the GridItem component is allowed within the conditional rendering statement.
2. Update mechanism
When the value of the state variable used in the state judgment following if and else if changes, the conditional rendering statement will be updated. The update steps are as follows: 1. Evaluate the state judgment conditions of if and else if.
If the branch does not change , please do not need to perform the following steps. If there are changes in the branch, perform steps 2 and 3:
2. Delete all subcomponents previously built.
3. Execute the constructor of the new branch and add the obtained components to the if parent container. If the applicable else branch is missing, nothing is built.
Conditions can include Typescript expressions. For expressions in constructors, such expressions must not change application state.
3. Usage Scenario
1. Use if for conditional rendering

@Entry
@Component
struct ViewA {
  @State count: number = 0;

  build() {
    Column() {
      Text(`count=${this.count}`)

      if (this.count > 0) {
        Text(`count is positive`)
          .fontColor(Color.Green)
      }

      Button('increase count')
        .onClick(() => {
          this.count++;
        })

      Button('decrease count')
        .onClick(() => {
          this.count--;
        })
    }
  }
}

Each branch of the if statement contains a constructor function. Such a constructor must create one or more subcomponents. On initial render, the if statement executes the build function and adds the resulting child component to its parent component.
Whenever the state variable used in an if or else if conditional statement changes, the conditional statement updates and re-evaluates the new condition value. If the condition value evaluation changes, this means another conditional branch needs to be constructed. At this point the ArkUI framework will:
1. Delete all previously rendered (early branch) components.
2. Execute the constructor of the new branch and add the generated subcomponent to its parent component.
In the above example, if count increases from 0 to 1, then the if statement is updated and the condition count > 0 will be re-evaluated and the evaluation result will change from false to true. Therefore, the constructor of the true branch will be executed, a Text component will be created, and it will be added to the parent component Column. If subsequent count changes to 0, the Text component will be removed from the Column component. Since there is no else branch, the new constructor will not be executed.
2.if…else…statements and subcomponent states
The following example contains if…else…statements and subcomponents with @State decorated variables.

@Component
struct CounterView {
  @State counter: number = 0;
  label: string = 'unknown';

  build() {
    Row() {
      Text(`${this.label}`)
      Button(`counter ${this.counter} +1`)
        .onClick(() => {
          this.counter += 1;
        })
    }
  }
}

@Entry
@Component
struct MainView {
  @State toggle: boolean = true;

  build() {
    Column() {
      if (this.toggle) {
        CounterView({ label: 'CounterView #positive' })
      } else {
        CounterView({ label: 'CounterView #negative' })
      }
      Button(`toggle ${this.toggle}`)
        .onClick(() => {
          this.toggle = !this.toggle;
        })
    }
  }
}

CounterView (labeled 'CounterView #positive') subcomponent is created when it is first rendered. This subcomponent carries a state variable named counter. When the CounterView.counter state variable is modified, the CounterView (labeled as 'CounterView #positive') subcomponent will retain the state variable value when re-rendered. When the value of the MainView.toggle state variable changes to false, the if statement within the MainView parent component will be updated, and subsequently the CounterView (labeled 'CounterView #positive') child component will be removed. At the same time, a new CounterView (labeled 'CounterView #negative') instance will be created. And its own counter state variable is set to the initial value 0.
Note: CounterView (label is 'CounterView #positive') and CounterView (label is 'CounterView #negative') are two different instances of the same custom component. Changes to the if branch will not update existing subcomponents, nor will state be preserved.
The following example shows the modifications that need to be made to retain the counter value when the condition changes.

@Component
struct CounterView {
  @Link counter: number;
  label: string = 'unknown';

  build() {
    Row() {
      Text(`${this.label}`)
      Button(`counter ${this.counter} +1`)
        .onClick(() => {
          this.counter += 1;
        })
    }
  }
}

@Entry
@Component
struct MainView {
  @State toggle: boolean = true;
  @State counter: number = 0;

  build() {
    Column() {
      if (this.toggle) {
        CounterView({ counter: $counter, label: 'CounterView #positive' })
      } else {
        CounterView({ counter: $counter, label: 'CounterView #negative' })
      }
      Button(`toggle ${this.toggle}`)
        .onClick(() => {
          this.toggle = !this.toggle;
        })
    }
  }
}

Here, the @State counter variable is owned by the parent component. Therefore, when the CounterView component instance is deleted, the variable will not be destroyed. The CounterView component references state through the @Link decorator. State must be moved from the child to its parent (or parent's parent) to avoid losing state when conditional or duplicate content is destroyed.
3. Nested if statements
The nesting of conditional statements has no impact on the relevant rules of the parent component.

@Entry
@Component
struct CompA {
  @State toggle: boolean = false;
  @State toggleColor: boolean = false;

  build() {
    Column() {
      Text('Before')
        .fontSize(15)
      if (this.toggle) {
        Text('Top True, positive 1 top')
          .backgroundColor('#aaffaa').fontSize(20)
        // 内部if语句
        if (this.toggleColor) {
          Text('Top True, Nested True, positive COLOR  Nested ')
            .backgroundColor('#00aaaa').fontSize(15)
        } else {
          Text('Top True, Nested False, Negative COLOR  Nested ')
            .backgroundColor('#aaaaff').fontSize(15)
        }
      } else {
        Text('Top false, negative top level').fontSize(20)
          .backgroundColor('#ffaaaa')
        if (this.toggleColor) {
          Text('positive COLOR  Nested ')
            .backgroundColor('#00aaaa').fontSize(15)
        } else {
          Text('Negative COLOR  Nested ')
            .backgroundColor('#aaaaff').fontSize(15)
        }
      }
      Text('After')
        .fontSize(15)
      Button('Toggle Outer')
        .onClick(() => {
          this.toggle = !this.toggle;
        })
      Button('Toggle Inner')
        .onClick(() => {
          this.toggleColor = !this.toggleColor;
        })
    }
  }
}

Guess you like

Origin blog.csdn.net/weixin_69135651/article/details/132407941