HarmonyOS 鸿蒙Next密码校验

HarmonyOS 鸿蒙Next密码校验

import { HMRouter, HMRouterMgr } from "@hadss/hmrouter";
import { PAGE_PATH, TabContentTitle } from "base";
import { getAppSafeArea } from "base/src/main/ets/commons/utils/common";
import { AppStorageV2 } from "@kit.ArkUI";

@HMRouter({ pageUrl: PAGE_PATH.create_new_password_login })
@ComponentV2
export struct createNewPasswordLogin {
  @Local text: string = '';
  controller: TextInputController = new TextInputController();

  safeArea: getAppSafeArea = AppStorageV2.connect(getAppSafeArea, () => new getAppSafeArea())!
  handleBack() {
    HMRouterMgr.pop()
  }
  @Local password:string=''
  @Local newPassword:string=''
  @Local isPassword:boolean=false
  @Local isNewPassword:boolean=false
  @Local passWordSrc1:ResourceStr=$r('[base].media.display')
  @Local passWordSrc2:ResourceStr=$r('[base].media.notDisplay')
  @Local creatPassError:string=''
  @Local creatNewPassError:string=''

  validatePassword() {
    if (this.password.length < 8 || this.password.length > 12) {
      this.creatPassError = 'Your password must be 8-12 characters long.'
    } else {
      this.creatPassError = ''
    }
  }

  build() {
    Column() {
      TabContentTitle({onBack: () => {
        this.handleBack() // 将父组件的处理函数传递给子组件
      }})
      Text($r('[base].string.createNewPassTitle'))
        .fontColor('#303030')
        .fontWeight(700)
        .fontSize(20)
        .lineHeight(20)
        .width('100%')
        .textAlign(TextAlign.Start)
        .margin({ bottom: 10, top: 10 })
      Text($r('[base].string.createNewPassContent'))
        .fontColor('#686868')
        .fontSize(18)
        .lineHeight(16)
        .fontWeight(500)
        .width('100%')
        .textAlign(TextAlign.Start)
        .margin({ bottom: 10, top: 10 })
      Text() {
        Span($r('[base].string.createNewPassWord')).fontColor('#303030').fontSize(20).fontWeight(600)
        Span('*').fontColor('#EB3327')
      }.width('100%').textAlign(TextAlign.Start)

      TextInput({ text: this.password!!, controller: this.controller })
        .placeholderColor(Color.Grey)
        .placeholderFont({ size: 14, weight: 400 })
        .contentType(ContentType.EMAIL_ADDRESS)
        .width('100%')
        .height(40)
        .margin(20)
        .fontSize(14)
        .fontColor(Color.Black)
        .borderRadius(8)
        .type(InputType.Password)
        .passwordIcon({ onIconSrc: this.passWordSrc1, offIconSrc: this.passWordSrc2 })
        .showError(this.creatPassError)
        .onBlur(()=>{
          if (this.password==''){
            this.isPassword=true
          }
        })
        .onChange(()=>{
            this.validatePassword()
        })

      Text() {
        Span($r('[base].string.createNewPassConfirm')).fontColor('#303030').fontSize(20).fontWeight(600)
        Span('*').fontColor('#EB3327')
      }.width('100%').textAlign(TextAlign.Start).margin({top:15,bottom:15})
      TextInput({ text: this.newPassword!!,controller: this.controller })
        .placeholderColor(Color.Grey)
        .placeholderFont({ size: 14, weight: 400 })
        .contentType(ContentType.EMAIL_ADDRESS)
        .type(InputType.Password)
        .passwordIcon({ onIconSrc: this.passWordSrc1, offIconSrc: this.passWordSrc2 })
        .width('100%')
        .height(40)
        .margin(20)
        .fontSize(14)
        .fontColor(Color.Black)
        .borderRadius(8)
        .showError(this.creatNewPassError)
        .onSubmit((enterKey: EnterKeyType, event: SubmitEvent)=>{
          if(this.password===this.newPassword){
            this.creatNewPassError='Does not match the password entered.'
          }
        })
        .onBlur(()=>{
          if (this.newPassword==''){
            this.isNewPassword=true
          }
        })

      Column().width('100%').layoutWeight(1)

      if (this.isNewPassword==true && this.isPassword==true){
        Button($r('[base].string.createNewPassCode'), { type: ButtonType.Normal, stateEffect: true })
          .borderRadius(8)
          .linearGradient({
            angle: 90,
            colors: [
              [0xF64470, 0.0],
              [0xFFAA33, 1.0]
            ]
          })
          .fontColor('#FFFFFF')
          .width('90%')
          .onClick(() => {
            HMRouterMgr.push({
              pageUrl: PAGE_PATH.login
            })
          })
          .margin({ top: 40, bottom: 15 })
          .width('100%')

      } else {
        Button($r('[base].string.createNewPassCode'), { type: ButtonType.Normal, stateEffect: true })
          .borderRadius(8)
          .backgroundColor('#E1E1E1')
          .fontColor('#878787')
          .width('90%')
          .margin({ top: 40, bottom: 15 })
          .width('100%')
      }

    }
    .padding({
      bottom: this.safeArea.bottomHeight,
      top: this.safeArea.topHeight,
      right: 15,
      left: 15
    })
    .width('100%')
    .layoutWeight(1)
    .backgroundColor('#F8F8F8')
  }
}

更多关于HarmonyOS 鸿蒙Next密码校验的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

楼主你的需求是这样吗?

  1. 第一个密码框(password) 输入完成(onBlur)时:如果密码长度 < 8 或 > 12,显示错误提示。

  2. 第二个密码框(newPassword) 输入完成(onBlur)时:如果密码长度 < 8 或 > 12,显示错误提示。如果和第一个密码不一致,显示错误提示。

你的当前代码逻辑有点问题,尤其是在 onSubmit 里只判断了一次不一致错误,且判断语句也写反了。建议你抽出校验方法并统一管理,防止混乱。

很多没法跑,楼主试下这个代码:

import { HMRouter, HMRouterMgr } from "@hadss/hmrouter";
import { PAGE_PATH, TabContentTitle } from "base";
import { getAppSafeArea } from "base/src/main/ets/commons/utils/common";
import { AppStorageV2 } from "@kit.ArkUI";

@HMRouter({ pageUrl: PAGE_PATH.create_new_password_login })
@ComponentV2
export struct createNewPasswordLogin {
  @Local text: string = '';
  controller: TextInputController = new TextInputController();

  safeArea: getAppSafeArea = AppStorageV2.connect(getAppSafeArea, () => new getAppSafeArea())!

  handleBack() {
    HMRouterMgr.pop()
  }

  @Local password: string = ''
  @Local newPassword: string = ''
  @Local isPassword: boolean = false
  @Local isNewPassword: boolean = false
  @Local passWordSrc1: ResourceStr = $r('[base].media.display')
  @Local passWordSrc2: ResourceStr = $r('[base].media.notDisplay')
  @Local creatPassError: string = ''
  @Local creatNewPassError: string = ''
  @Local isFormValid: boolean = false

  validatePassword() {
    if (this.password.length < 8 || this.password.length > 12) {
      this.creatPassError = 'Your password must be 8-12 characters long.'
    } else {
      this.creatPassError = ''
    }
    this.updateFormValidState()
  }

  validateNewPassword() {
    if (this.newPassword.length < 8 || this.newPassword.length > 12) {
      this.creatNewPassError = 'Your password must be 8-12 characters long.'
    } else if (this.newPassword !== this.password) {
      this.creatNewPassError = 'Does not match the password entered.'
    } else {
      this.creatNewPassError = ''
    }
    this.updateFormValidState()
  }

  updateFormValidState() {
    this.isFormValid =
      this.creatPassError === '' &&
        this.creatNewPassError === '' &&
        this.password !== '' &&
        this.newPassword !== ''
  }

  build() {
    Column() {
      TabContentTitle({
        onBack: () => {
          this.handleBack()
        }
      })

      Text($r('[base].string.createNewPassTitle'))
        .fontColor('#303030')
        .fontWeight(700)
        .fontSize(20)
        .lineHeight(20)
        .width('100%')
        .textAlign(TextAlign.Start)
        .margin({ bottom: 10, top: 10 })

      Text($r('[base].string.createNewPassContent'))
        .fontColor('#686868')
        .fontSize(18)
        .lineHeight(16)
        .fontWeight(500)
        .width('100%')
        .textAlign(TextAlign.Start)
        .margin({ bottom: 10, top: 10 })

      Text() {
        Span($r('[base].string.createNewPassWord'))
          .fontColor('#303030')
          .fontSize(20)
          .fontWeight(600)
        Span('*')
          .fontColor('#EB3327')
      }
      .width('100%')
      .textAlign(TextAlign.Start)

      TextInput({ text: this.password!!, controller: this.controller })
        .placeholderColor(Color.Grey)
        .placeholderFont({ size: 14, weight: 400 })
        .contentType(ContentType.EMAIL_ADDRESS)
        .width('100%')
        .height(40)
        .margin(20)
        .fontSize(14)
        .fontColor(Color.Black)
        .borderRadius(8)
        .type(InputType.Password)
        .passwordIcon({ onIconSrc: this.passWordSrc1, offIconSrc: this.passWordSrc2 })
        .showError(this.creatPassError)
        .onBlur(() => {
          this.isPassword = this.password === ''
          this.validatePassword()
        })
        .onChange(() => {
          this.validatePassword()
        })

      Text() {
        Span($r('[base].string.createNewPassConfirm'))
          .fontColor('#303030')
          .fontSize(20)
          .fontWeight(600)
        Span('*')
          .fontColor('#EB3327')
      }
      .width('100%')
      .textAlign(TextAlign.Start)
      .margin({ top: 15, bottom: 15 })

      TextInput({ text: this.newPassword!!, controller: this.controller })
        .placeholderColor(Color.Grey)
        .placeholderFont({ size: 14, weight: 400 })
        .contentType(ContentType.EMAIL_ADDRESS)
        .type(InputType.Password)
        .passwordIcon({ onIconSrc: this.passWordSrc1, offIconSrc: this.passWordSrc2 })
        .width('100%')
        .height(40)
        .margin(20)
        .fontSize(14)
        .fontColor(Color.Black)
        .borderRadius(8)
        .showError(this.creatNewPassError)
        .onBlur(() => {
          this.isNewPassword = this.newPassword === ''
          this.validateNewPassword()
        })
        .onChange(() => {
          this.validateNewPassword()
        })

      Column().width('100%').layoutWeight(1)

      if (this.isFormValid) {
        Button($r('[base].string.createNewPassCode'), { type: ButtonType.Normal, stateEffect: true })
          .borderRadius(8)
          .linearGradient({
            angle: 90,
            colors: [
              [0xF64470, 0.0],
              [0xFFAA33, 1.0]
            ]
          })
          .fontColor('#FFFFFF')
          .width('90%')
          .onClick(() => {
            HMRouterMgr.push({
              pageUrl: PAGE_PATH.login
            })
          })
          .margin({ top: 40, bottom: 15 })
          .width('100%')
      } else {
        Button($r('[base].string.createNewPassCode'), { type: ButtonType.Normal, stateEffect: true })
          .borderRadius(8)
          .backgroundColor('#E1E1E1')
          .fontColor('#878787')
          .width('90%')
          .margin({ top: 40, bottom: 15 })
          .width('100%')
      }
    }
    .padding({
      bottom: this.safeArea.bottomHeight,
      top: this.safeArea.topHeight,
      right: 15,
      left: 15
    })
    .width('100%')
    .layoutWeight(1)
    .backgroundColor('#F8F8F8')
  }
}

更多关于HarmonyOS 鸿蒙Next密码校验的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


看不懂你的长难句

鸿蒙Next的密码校验主要使用ArkTS的安全模块实现。通过@ohos.security.cryptoFramework提供的API进行密码哈希和校验:

  1. 使用cryptoFramework.createMd()创建MD实例
  2. 调用md.update()输入明文密码
  3. 通过md.digest()生成哈希值
  4. 校验时比对存储的哈希值

关键代码示例:

let md = cryptoFramework.createMd("SHA256");
md.update(inputPassword);
let passwordHash = await md.digest();

安全注意事项:

  • 必须使用盐值加密
  • 推荐采用SHA256或更强算法
  • 敏感数据需存放在安全沙箱,

从代码来看,您已经实现了基本的密码校验逻辑,但需要调整校验触发时机。以下是针对HarmonyOS Next的优化建议:

  1. 第一个密码校验(8-12位): 当前是在onChange时触发校验,建议改为onBlur时校验更符合需求:
.onBlur(() => {
  this.validatePassword()
  if(this.password === '') {
    this.isPassword = true
  }
})
  1. 第二个密码校验: 需要添加长度校验和一致性校验:
validateNewPassword() {
  if(this.newPassword.length < 8 || this.newPassword.length > 12) {
    this.creatNewPassError = 'Password must be 8-12 characters'
  } else if(this.password !== this.newPassword) {
    this.creatNewPassError = 'Passwords do not match'
  } else {
    this.creatNewPassError = ''
  }
}

// 在TextInput中添加
.onBlur(() => {
  this.validateNewPassword()
  if(this.newPassword === '') {
    this.isNewPassword = true
  }
})
  1. 提交按钮状态: 当前逻辑是当两个字段非空时才启用按钮,建议增加校验通过的条件:
if(this.isNewPassword && this.isPassword && !this.creatPassError && !this.creatNewPassError)

这些调整将使校验逻辑更符合需求描述,在适当时机触发校验。注意保持代码中已有的安全区域适配和样式设置。

回到顶部