harmony 鸿蒙!! Syntax: Two-Way Binding

  • 2025-06-12
  • 浏览 (4)

!! Syntax: Two-Way Binding

In state management V1, $$ is used for two-way binding of built-in components. In state management V2, the !! syntactic sugar is used to implement two-way binding of components in a unified manner.

NOTE

The !! syntax is supported since API version 12.

Overview

!! is a syntactic sugar used to implement two-way binding of components in initialization of \@Param and \@Event of the child components. The \@Event method name must be declared as “$” + \@Param attribute name. For details, see Use Scenarios.

  • If the parent component uses !!, the change of the parent component will be synchronized to the child component, and vice versa.
  • If the parent component does not use !!, the change of the parent component is unidirectional.

Use Scenarios

Two-Way Binding Between Custom Components

  1. Construct the Star child component in the Index component, bind the value in the parent and child components bidirectionally, and initialize @Param value and @Event $value of the child component.

  2. The two-way binding syntactic sugar can be considered as:

    Star({ value: this.value, $value: (val: number) => { this.value = val }})
    
  3. Click the button in the Index component to change the value, and Text in both the parent component Index and child component Star will be updated.

  4. Click the button in the child component Star to invoke this.$value(10), and Text in both the parent component Index and child component Star will be updated.

@Entry
@ComponentV2
struct Index {
  @Local value: number = 0;

  build() {
    Column() {
      Text(`${this.value}`)
      Button(`change value`).onClick(() => {
        this.value++;
      })
      Star({ value: this.value!! })
    }
  }
}


@ComponentV2
struct Star {
  @Param value: number = 0;
  @Event $value: (val: number) => void = (val: number) => {};

  build() {
    Column() {
      Text(`${this.value}`)
      Button(`change value `).onClick(() => {
        this.$value(10);
      })
    }
  }
}

Constraints

  • !! does not support multi-layer parent-child component transfer.
  • !! cannot be used together with @Event. Since API version 18, when !! is used to pass parameters to the @Event method of a child component, a compilation error is reported.
  • When three or more exclamation marks (!!!, !!!!, or !!!!!) are used, two-way binding is not supported.

Two-Way Binding Between Built-in Component Parameters

The !! operator provides a TypeScript variable by-reference to a built-in component so that the variable value and the internal state of that component are kept in sync. Add this operator after the variable name, for example, isShow!!.

What the internal state is depends on the component. For example, the isShow parameter of the bindMenu component.

Rules of Use

  • Currently, !! supports two-way binding of the following parameters of the basic types, that is, the parameters can synchronize the current menu or popup state. In addition, !! supports two-way binding of variables of the basic types as well. When a variable is decorated by \@Local of V2 or \@State of V1, the change of the variable value triggers the UI re-render.
Attribute Supported Parameter Initial API Version
bindMenu isShow 13
bindContextMenu isShown 13
bindPopup show 13
TextInput text 18
TextArea text 18
Search value 18
BindSheet isShow 18
BindContentCover isShow 18
Toggle isOn 18
Checkbox select 18
CheckboxGroup selectAll 18
Radio checked 18
Rating rating 18
Slider value 18
Select selected 18
Select value 18
MenuItem selected 18
  • When the \@Local decorated variable bound to !! changes, the UI is rendered synchronously.

Example

Two-way binding of the isShow parameter of the bindMenu API:

@Entry
@ComponentV2
struct BindMenuInterface {
  @Local isShow: boolean = false;

  build() {
    Column() {
      Row() {
        Text('click show Menu')
          .bindMenu(this.isShow!!, // Two-way binding.
            [
              {
                value: 'Menu1',
                action: () => {
                  console.info('handle Menu1 click');
                }
              },
              {
                value: 'Menu2',
                action: () => {
                  console.info('handle Menu2 click');
                }
              },
            ])
      }.height('50%')
      Text("isShow: " + this.isShow).fontSize(18).fontColor(Color.Red)
      Row() {
        Button("Click")
          .onClick(() => {
            this.isShow = true;
          })
          .width(100)
          .fontSize(20)
          .margin(10)
      }
    }.width('100%')
  }
}

bindMenu

你可能感兴趣的鸿蒙文章

harmony 鸿蒙\@AnimatableExtend Decorator: Definition of Animatable Attributes

harmony 鸿蒙Application State Management Overview

harmony 鸿蒙AppStorage: Storing Application-wide UI State

harmony 鸿蒙Basic Syntax Overview

harmony 鸿蒙\@Builder Decorator: Custom Builder Function

harmony 鸿蒙\@BuilderParam Decorator: Referencing the \@Builder Function

harmony 鸿蒙Creating a Custom Component

harmony 鸿蒙Mixing Use of Custom Components

harmony 鸿蒙Constraints on Access Modifiers of Custom Component Member Variables

harmony 鸿蒙Freezing a Custom Component

0  赞