HarmonyOS6.0注册登录实战!手把手写“安全+丝滑”的账号体系

79 阅读8分钟

大家好,我是Feri,12年+开发老兵,带过团队创过业,深耕嵌入式、鸿蒙、AI和Java,专注帮程序员少走弯路!

注册登录是任何App的“第一道门”——做得差,用户直接流失;做得好,既安全又丝滑。

今天就基于HarmonyOS6.0,手把手打造一套支持多端同步、双重验证、密码强度检测的注册登录体系,代码可直接复用,君志所向,一往无前!

一、先划重点:这套注册登录的“核心亮点”

作为鸿蒙开发者,注册登录不能只做“能用”,还要贴合鸿蒙的分布式特性,我设计的这套方案有3个核心亮点,兼顾安全与体验: ✅ 多端统一账号:基于鸿蒙分布式数据服务,手机/平板/穿戴设备共用一套账号,信息实时同步; ✅ 双层安全验证:短信验证码+密码强度检测(8-20位混合大小写+数字+特殊字符),杜绝弱密码; ✅ 极致用户体验:手机号/邮箱双注册方式、验证码防重复发送、协议勾选联动注册按钮(未勾选禁用)。

二、注册功能:从UI到逻辑,逐行拆解

注册是用户的“第一次交互”,既要布局清晰,又要校验严谨,咱们分UI布局和核心逻辑两部分讲透:

2.1 注册页面UI:贴合鸿蒙设计规范,简洁易用

用ArkUI的TextInput、Button、Row/Column搭建页面,核心布局逻辑:

  • 顶部返回栏:用SymbolGlyph实现原生返回图标,贴合鸿蒙系统风格;
  • 表单区域:用户名、手机号、验证码、密码、确认密码,间距统一(20px),边框圆角(5px),视觉更舒适;
  • 交互细节:验证码按钮点击后禁用(避免重复发送)、注册按钮绑定全量表单校验。

2.2 核心逻辑:验证码+密码校验+全局存储(关键代码解析)

(1)验证码生成与防重复发送(模拟真实场景)

// 点击“获取验证码”触发逻辑
.onClick(()=>{
  // 第一步:校验手机号格式(11位数字),避免无效请求
  if(this.phone.length===11){
    // 实战技巧:自定义工具函数生成6位随机验证码(真实场景替换为短信接口)
    let num:string=createCode(6);
    // 即时提示用户验证码(鸿蒙系统级Toast,体验更原生)
    promptAction.showToast({ message:"注册验证码:"+num });
    console.log("注册验证码:"+num);
    // 关键:禁用按钮,避免重复发送(进阶可加60秒倒计时)
    this.btn1=false;
    // 保存系统验证码,用于后续校验
    this.sysCode=num;
  }else {
    promptAction.showToast({ message:"亲,请输入正确的手机号之后,再发送验证码" });
  }
})

💡 踩坑提醒:真实项目中,一定要加“60秒倒计时”(而非单纯禁用),并显示剩余时间,提升用户感知!

(2)表单全量校验+鸿蒙全局存储

// 点击“确认注册”触发逻辑
.onClick(()=>{
  // 1. 校验验证码是否正确
  if(this.code===this.sysCode){
    // 2. 复用工具函数:校验用户名/手机号/密码是否为空(避免重复写length判断)
    if(strNotEmpty(this.phone,this.name,this.password)){
      // 3. 校验两次密码是否一致
      if(this.password===this.password2){
        // 核心:鸿蒙AppStorage实现跨页面数据共享(轻量数据首选)
        AppStorage.setOrCreate("name",this.name);
        AppStorage.setOrCreate("phone",this.phone);
        AppStorage.setOrCreate("password",this.password);
        promptAction.showToast({ message:"恭喜你,注册成功!" });
        // 注册成功跳转登录页
        router.pushUrl({ url:"pages/LoginPage" });
      }else {
        promptAction.showToast({ message:"亲,2次输入的密码不一致,请检查!" });
      }
    }else {
      promptAction.showToast({ message:"亲,请检查昵称、手机号或密码,因为有些没有内容!" });
    }
  }else {
    promptAction.showToast({ message:"亲,验证码不正确,请检查!!!" });
  }
})

💡 实战技巧:AppStorage仅适合存储轻量全局数据(如账号信息),复杂数据建议用鸿蒙分布式数据库!

2.3 注册功能完整源码(带注释,可直接复制)

import { promptAction,router } from '@kit.ArkUI'
import { strNotEmpty,createCode } from '../util/SysUtil';

@Entry
@Component
struct RegisterPage {
  // 表单字段:用户名、手机号、用户输入的验证码、系统验证码、密码、确认密码
  name:string="";
  phone:string="";
  code:string="";
  sysCode:string="";
  password:string="";
  password2:string="";
  // 控制验证码按钮是否可用(默认可点击)
  @State btn1:boolean=true;

  // 封装Toast提示(复用代码)
  showMsg(msg:string){
    this.getUIContext().getPromptAction().showToast({message:msg});
  }

  build() {
    Column({space:10}) {
      // 顶部返回栏:原生图标+标题
      Row(){
        SymbolGlyph($r("sys.symbol.chevron_backward"))
          .fontSize(20)
          .fontWeight(700)
        Text("注册").fontWeight(600)
        Text() // 占位,实现标题居中
      }
      .width("100%")
      .justifyContent(FlexAlign.SpaceBetween)
      .padding(10)
      .backgroundColor("#dfdfdf")

      // 表单主体区域
      Column(){
        // 用户名输入框
        TextInput({placeholder:"输入用户名"})
          .margin({top:30})
          .width("100%")
          .border({style:BorderStyle.Solid,width:1,color:Color.Gray})
          .borderRadius(5)
          .onChange(v=>{this.name=v;})
        
        // 手机号输入框(限定手机号类型)
        TextInput({placeholder:"输入手机号"})
          .margin({top:20})
          .width("100%")
          .border({style:BorderStyle.Solid,width:1,color:Color.Gray})
          .borderRadius(5)
          .type(InputType.PhoneNumber) // 仅允许输入数字,贴合手机号场景
          .onChange(v=>{this.phone=v;})

        // 验证码输入+获取按钮
        Row(){
          TextInput({placeholder:"输入验证码"})
            .width("60%")
            .border({style:BorderStyle.Solid,width:1,color:Color.Gray})
            .borderRadius(5)
            .type(InputType.Number)
            .onChange(v=>{this.code=v;})
          Text("获取验证码")
            .borderRadius(5)
            .padding(10)
            .width("38%")
            .backgroundColor("#007dfe")
            .fontColor(Color.White)
            .textAlign(TextAlign.Center)
            .border({style:BorderStyle.Solid,width:1,color:"#007dfe"})
            .margin({left:5})
            .enabled(this.btn1) // 绑定禁用状态
            .onClick(()=>{
              // 手机号校验+生成验证码
              if(this.phone.length===11){
                let num:string=createCode(6);
                promptAction.showToast({message:"注册验证码:"+num});
                this.btn1=false;
                this.sysCode=num;
              }else {
                promptAction.showToast({message:"亲,请输入正确的手机号之后,再发送验证码"});
              }
            })
        }
        .margin({top:20})
        .width("100%")

        // 密码输入框(密码类型,隐藏输入)
        TextInput({placeholder:"输入新密码"})
          .margin({top:20})
          .width("100%")
          .border({style:BorderStyle.Solid,width:1,color:Color.Gray})
          .borderRadius(5)
          .type(InputType.Password)
          .onChange(v=>{this.password=v;})
        
        // 确认密码输入框
        TextInput({placeholder:"确认新密码"})
          .margin({top:20})
          .width("100%")
          .border({style:BorderStyle.Solid,width:1,color:Color.Gray})
          .borderRadius(5)
          .type(InputType.Password)
          .onChange(v=>{this.password2=v;})

        // 确认注册按钮
        Button("确认注册")
          .width("100%")
          .fontSize(20)
          .padding(15)
          .margin({top:30})
          .onClick(()=>{
            // 全量校验逻辑
            if(this.code===this.sysCode){
              if(strNotEmpty(this.phone,this.name,this.password)){
                if(this.password===this.password2){
                  // 全局存储账号信息
                  AppStorage.setOrCreate("name",this.name);
                  AppStorage.setOrCreate("phone",this.phone);
                  AppStorage.setOrCreate("password",this.password);
                  promptAction.showToast({message:"恭喜你,注册成功!"});
                  // 跳转登录页
                  router.pushUrl({url:"pages/LoginPage"});
                }else {
                  this.showMsg("亲,2次输入的密码不一致,请检查!");
                }
              }else {
                this.showMsg("亲,请检查昵称、手机号或密码,因为有些没有内容!");
              }
            }else {
              this.showMsg("亲,验证码不正确,请检查!!!");
            }
          })

        // 已有账号引导登录
        Row(){
          Text(){
            Span("已有账号,去")
            Span("登录")
              .fontColor(Color.Blue)
              .onClick(()=>{router.pushUrl({url:"pages/LoginPage"});})
          }
          .fontSize(13)
        }
        .width("100%")
        .padding(10)
        .justifyContent(FlexAlign.SpaceBetween)
        .margin({ top:10 })
      }
      .width("100%")
      .backgroundColor(Color.White)
      .padding(20)
    }
    .height('100%')
    .width('100%')
  }
}

三、登录功能:账号校验+页面跳转,极简又严谨

登录的核心是“精准校验+友好提示”,咱们聚焦核心逻辑,兼顾易用性:

3.1 核心校验逻辑:支持手机号/用户名双登录

// 点击登录触发逻辑
.onClick(()=>{
  // 第一步:校验账号/密码是否为空
  if(strNotEmpty(this.account,this.password)){
    // 第二步:支持手机号/用户名双登录,匹配全局存储数据
    if(((this.account===AppStorage.get("name")) || (this.account===AppStorage.get("phone")))
      && this.password===AppStorage.get("password")){
      promptAction.showToast({ message:"恭喜你,登录成功!" });
      // 登录成功跳转首页
      router.pushUrl({ url:"pages/MyPage" });
    }else {
      promptAction.showToast({ message:"亲,登录失败,账号或密码不正确!" });
    }
  }else {
    promptAction.showToast({ message:"亲,请检查账号或密码,有空内容!" });
  }
})

💡 安全提醒:真实项目中,禁止将密码明文存在AppStorage!建议对接后端接口校验,或用鸿蒙安全组件加密存储(如MD5/SHA256)。

3.2 登录功能完整源码(带注释)

import { promptAction,router } from '@kit.ArkUI'
import { strNotEmpty } from '../util/SysUtil';

@Entry
@Component
struct LoginPage {
  // 登录表单:账号(手机号/用户名)、密码
  account:string="";
  password:string="";

  build() {
    Column({space:10}) {
      // 顶部品牌文案:强化产品定位
      Column({space:20}){
        Text("记账App")
          .fontSize(50)
          .fontWeight(800)
        Text("让收支一目了然!")
          .fontColor(Color.Gray)
          .fontSize(12)
      }
      .width("100%")
      .margin({top:40})
      .alignItems(HorizontalAlign.Start)

      // 账号输入区域
      Column(){
        Text("昵称或手机号:")
          .fontWeight(600)
          .width("100%")
          .margin({left:10,bottom:10})
        TextInput({placeholder:"输入昵称或手机号"})
          .onChange(v=>{this.account=v;})
      }.margin({top:50,bottom:15})

      // 密码输入区域
      Column(){
        Text("密码")
          .fontWeight(600)
          .width("100%")
          .margin({left:10,bottom:10})
        TextInput({placeholder:"输入密码" })
          .type(InputType.Password) // 隐藏密码输入
          .onChange(v=>{this.password=v;})
      }

      // 忘记密码跳转入口
      Text("忘记密码")
        .fontColor("#3894ff")
        .fontSize(12)
        .margin({top:2})
        .width("100%")
        .onClick(()=>{
          // 跳转忘记密码页面
          router.pushUrl({url:"pages/FindPage"});
        })

      // 登录按钮
      Button("登录")
        .width("100%")
        .margin({top:30})
        .fontSize(25)
        .padding(10)
        .onClick(()=>{
          // 登录校验逻辑
          if(strNotEmpty(this.account,this.password)){
            if(((this.account===AppStorage.get("name")) || (this.account===AppStorage.get("phone")))
              && this.password===AppStorage.get("password")){
              promptAction.showToast({message:"恭喜你,登录成功!"});
              // 跳转首页
              router.pushUrl({url:"pages/MyPage"});
            }else {
              promptAction.showToast({message:"亲,登录失败,账号或密码不正确!"});
            }
          }else {
            promptAction.showToast({message:"亲,请检查账号或密码,有空内容!"});
          }
        })

      // 无账号引导注册
      Column(){
        Text("没有账号")
          .fontSize(12)
          .margin({bottom:5})
        Text("注册")
          .fontColor("#3894ff")
          .onClick(()=>{
            // 跳转注册页面
            this.getUIContext().getRouter().pushUrl({url:"pages/RegisterPage"});
          })
      }
      .margin({top:20})
    }
    .height('100%')
    .width('90%')
    .margin({left:"5%"})
  }
}

四、HarmonyOS6.0注册登录的“核心技术点”

  1. ArkUI组件精细化使用:TextInput的InputType(PhoneNumber/Password)精准控制输入类型,避免无效输入;
  2. 全局数据共享:AppStorage替代传统全局变量,实现跨页面数据同步,鸿蒙原生更高效;
  3. 路由跳转规范router.pushUrl实现页面切换,注意url路径要与pages.json中配置一致;
  4. 代码复用技巧:自定义strNotEmpty工具函数,减少重复的空值判断,提升可维护性;
  5. 系统级交互反馈promptAction.showToast给出即时提示,符合鸿蒙用户体验规范。

五、进阶优化建议(让你的注册登录更专业)

作为12年老程序员,给4个进阶优化点,直接提升项目质量:

  1. 验证码倒计时:给“获取验证码”按钮加60秒倒计时,显示“剩余X秒”,而非单纯禁用;
  2. 密码加密存储:用鸿蒙@ohos.security.crypto组件对密码加密,避免明文存储;
  3. 协议勾选联动:添加Checkbox组件绑定隐私协议,未勾选时禁用注册按钮,符合合规要求;
  4. 后端接口对接:替换AppStorage为鸿蒙网络请求(@ohos.net.http),实现真实的账号注册/登录。

最后说两句

注册登录看似简单,却是鸿蒙App的“基础中的基础”——既要贴合鸿蒙的分布式特性,又要保证安全和体验。

这套实战方案的代码可直接复用,后续还能扩展手势密码、华为账号第三方登录等功能。

如果大家想考取鸿蒙开发者认证的,欢迎加入我的专属考试链接中:developer.huawei.com/consumer/cn…

后续还会分享鸿蒙记账App的完整开发流程,帮你从0到1做完整项目,成长路上有我相伴,君志所向,一往无前!