HarmonyOS鸿蒙Next中如何实现两个TextInput双向绑定?

HarmonyOS鸿蒙Next中如何实现两个TextInput双向绑定? 如何实现两个 TextInput双向绑定?通过onchange事件,输入A输入框的时候,把值计算乘以10填到B ,当输入B的时候,把值计算减10填到A。目前遇到bug输入小数点了之后,再输入一个数字就不触发了。通过布尔类型判断防止循环触发onchange事件。

4 回复

原因分析:根据提供的代码发现,因为输入小数点的时候没有触发onchange事件导致flag标记没重置,就会出现A输入值后,B的值未发生改变

解决方案:通过焦点控制实现数值的计算和双向绑定

@Entry
@Component
struct DualInputLinkDecimal {
  @State valueA: string = '';
  @State valueB: string = '';
  // 记录当前操作源,防止死循环
  private activeInput: 'A' | 'B' | 'None' = 'None';
  build() {
    Column({ space: 20 }) {
      Text('双向联动 (支持小数 / 保留两位)')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 50, bottom: 20 })
      // ================= 输入框 A =================
      Row({ space: 15 }) {
        Text('输入框 A:')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
        TextInput({ text: $$this.valueA, placeholder: '输入A (B=A*10)' })
          .type(InputType.NUMBER_DECIMAL)
          .width('60%')
          .onFocus(() => {
            this.activeInput = 'A'; // 锁定计算源
          })
          .onBlur(() => {
            // 失去焦点时,把自己也格式化为两位小数
            let num = parseFloat(this.valueA);
            if (!isNaN(num)) 
              this.valueA = num.toFixed(2);
            }
          })
          .onChange((value: string) => {
            if (this.activeInput === 'A') {
              let numA = parseFloat(value);
              if (!isNaN(numA)) {
                this.valueB = (numA * 10).toFixed(2);
              } else {
                // 输入为空或仅输入 "-"、"." 时,清空联动框
                this.valueB = '';
              }
            }
          })
      }
      // ================= 输入框 B =================
      Row({ space: 15 }) {
        Text('输入框 B:')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
        TextInput({ text: $$this.valueB, placeholder: '输入B (A=B-10)' })
          .type(InputType.NUMBER_DECIMAL)
          .width('60%')
          .onFocus(() => {
            this.activeInput = 'B';
          })
          .onBlur(() => {
            // 失去焦点时,将自己格式化为两位小数
            let num = parseFloat(this.valueB);
            if (!isNaN(num)) {
              this.valueB = num.toFixed(2);
            }
          })
          .onChange((value: string) => {
            if (this.activeInput === 'B') {
              let numB = parseFloat(value);
              if (!isNaN(numB)) {
                // 计算 A = B - 10,并严格保留两位小数
                this.valueA = (numB - 10).toFixed(2);
              } else {
                this.valueA = '';
              }
            }
          })
      }
    }
    .width('100%')
    .padding(20)
  }
}

更多关于HarmonyOS鸿蒙Next中如何实现两个TextInput双向绑定?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


你设置inputType了?

InputType.Number

在HarmonyOS Next中,实现两个TextInput双向绑定可以使用@State@Watch装饰器。

  1. 定义@State变量存储输入值。
  2. 在TextInput组件中,使用value属性绑定该状态变量。
  3. 为每个TextInput的onChange事件添加处理函数,在函数中更新状态变量。
  4. 状态变量更新后,由于@State的响应式特性,所有绑定该变量的TextInput显示值会自动同步更新。

示例代码片段:

[@State](/user/State) message: string = ''
...
TextInput({ text: this.message })
  .onChange((value: string) => {
    this.message = value
  })
// 另一个TextInput同样绑定this.message

在HarmonyOS Next中实现两个TextInput的双向绑定,可以通过状态管理和事件回调来避免循环触发。以下是一个简洁的实现方案:

import { TextInput, Column } from '@kit.ArkUI';

@Entry
@Component
struct TwoWayBinding {
  @State textA: string = '';
  @State textB: string = '';
  @State updating: boolean = false; // 防止循环更新

  build() {
    Column() {
      TextInput({ text: this.textA })
        .onChange((value: string) => {
          if (!this.updating && value !== this.textA) {
            this.updating = true;
            this.textA = value;
            // 计算并更新B:A的值乘以10
            const num = parseFloat(value);
            this.textB = isNaN(num) ? '' : (num * 10).toString();
            this.updating = false;
          }
        })

      TextInput({ text: this.textB })
        .onChange((value: string) => {
          if (!this.updating && value !== this.textB) {
            this.updating = true;
            this.textB = value;
            // 计算并更新A:B的值减10
            const num = parseFloat(value);
            this.textA = isNaN(num) ? '' : (num - 10).toString();
            this.updating = false;
          }
        })
    }
  }
}

关键点说明:

  1. 使用updating标志:通过布尔变量防止onChange事件循环触发,确保一次只更新一个输入框。
  2. 数值处理:使用parseFloat转换字符串,并用isNaN检查有效性,避免无效计算。
  3. 条件更新:比较新旧值(value !== this.textA),减少不必要的状态变更。

针对小数点输入问题: 当输入小数点(如"1.")时,parseFloat会返回有效数字(1),因此不会中断触发。如果遇到输入中断,可能是由于状态更新与渲染时序问题,上述代码通过updating标志和值比较已做了规避。

此方案能稳定实现双向绑定和计算逻辑,同时处理边界情况。

回到顶部