img

一、案例介绍

本案例将展示如何在表单中使用LoadingProgress组件实现异步验证功能。通过在输入框旁显示加载动画,为用户提供实时的验证状态反馈,提升表单填写体验。

二、实现效果

  • 输入时显示验证状态
  • 异步验证过程动画
  • 验证结果及时反馈
  • 多字段并发验证

三、代码实现

1. 表单结构

@Entry
@Component
struct AsyncValidationForm {
  @State username: string = '';
  @State email: string = '';
  @State isValidatingUsername: boolean = false;
  @State isValidatingEmail: boolean = false;
  @State usernameError: string = '';
  @State emailError: string = '';
  private validationTimer: number = -1;

  build() {
    Column() {
      this.InputField({
        label: '用户名',
        value: this.username,
        isValidating: this.isValidatingUsername,
        error: this.usernameError,
        onChange: (value: string) => this.handleUsernameChange(value)
      })

      this.InputField({
        label: '邮箱',
        value: this.email,
        isValidating: this.isValidatingEmail,
        error: this.emailError,
        onChange: (value: string) => this.handleEmailChange(value)
      })

      Button('提交')
        .width('100%')
        .margin({ top: 24 })
        .enabled(this.isFormValid())
    }
    .width('100%')
    .padding(16)
    .gap(16)
  }
}

2. 输入字段实现

@Builder
InputField(options: {
  label: string,
  value: string,
  isValidating: boolean,
  error: string,
  onChange: (value: string) => void
}) {
  Column() {
    Row() {
      Text(options.label)
        .fontSize(16)
      if (options.isValidating) {
        LoadingProgress()
          .width(16)
          .height(16)
          .color('#2196F3')
          .margin({ left: 8 })
      }
    }
    .width('100%')
    .margin({ bottom: 8 })

    TextInput({ text: options.value })
      .width('100%')
      .height(48)
      .borderRadius(8)
      .backgroundColor('#F5F5F5')
      .borderWidth(options.error ? 1 : 0)
      .borderColor('#F44336')
      .onChange((value: string) => options.onChange(value))

    if (options.error) {
      Text(options.error)
        .fontSize(12)
        .fontColor('#F44336')
        .margin({ top: 4 })
    }
  }
}

3. 验证逻辑实现

private handleUsernameChange(value: string) {
  this.username = value;
  this.validateUsername();
}

private handleEmailChange(value: string) {
  this.email = value;
  this.validateEmail();
}

private validateUsername() {
  if (this.validationTimer !== -1) {
    clearTimeout(this.validationTimer);
  }

  if (this.username.length === 0) {
    this.usernameError = '';
    return;
  }

  this.isValidatingUsername = true;
  this.validationTimer = setTimeout(async () => {
    try {
      await this.checkUsernameAvailability(this.username);
      this.usernameError = '';
    } catch (error) {
      this.usernameError = error.message;
    } finally {
      this.isValidatingUsername = false;
    }
  }, 500);
}

private validateEmail() {
  if (this.validationTimer !== -1) {
    clearTimeout(this.validationTimer);
  }

  if (this.email.length === 0) {
    this.emailError = '';
    return;
  }

  this.isValidatingEmail = true;
  this.validationTimer = setTimeout(async () => {
    try {
      await this.checkEmailAvailability(this.email);
      this.emailError = '';
    } catch (error) {
      this.emailError = error.message;
    } finally {
      this.isValidatingEmail = false;
    }
  }, 500);
}

private checkUsernameAvailability(username: string): Promise<void> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (username.length < 3) {
        reject(new Error('用户名至少3个字符'));
      } else if (username === 'admin') {
        reject(new Error('用户名已被使用'));
      } else {
        resolve();
      }
    }, 1000);
  });
}

private checkEmailAvailability(email: string): Promise<void> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const emailRegex = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/;
      if (!emailRegex.test(email)) {
        reject(new Error('邮箱格式不正确'));
      } else if (email === 'admin@example.com') {
        reject(new Error('邮箱已被注册'));
      } else {
        resolve();
      }
    }, 1000);
  });
}

private isFormValid(): boolean {
  return this.username.length > 0 &&
         this.email.length > 0 &&
         !this.usernameError &&
         !this.emailError &&
         !this.isValidatingUsername &&
         !this.isValidatingEmail;
}

四、总结

本案例通过在表单中使用 LoadingProgress 组件实现了异步验证功能,为用户提供了实时的验证状态反馈。通过合理的状态管理和异步验证逻辑,实现了输入时的加载动画显示、验证结果的及时反馈以及多字段并发验证。这种实现方式适用于需要提升表单填写体验的场景,能够有效提升用户的交互体验。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐