鸿蒙原生开发手记:徒步迹 - 登录注册页面与表单校验
·

鸿蒙原生开发手记:徒步迹 - 登录注册页面与表单校验
实现完整的用户认证流程,包含表单验证和交互反馈
一、前言
登录注册是绝大多数 App 的入口功能。本文实现“徒步迹“的登录注册页面,包含手机号输入、密码输入、表单校验、Loading 状态等完整交互。
二、登录页面实现
2.1 布局设计
登录页分为三个区域:
- 标题区:品牌问候语
- 表单区:手机号、密码输入
- 操作区:登录按钮、注册入口
2.2 完整代码
@Entry
@Component
struct LoginPage {
@State private phone: string = '';
@State private password: string = '';
@State private showPassword: boolean = false;
@State private isLoading: boolean = false;
@State private errorMsg: string = '';
build() {
Column() {
// 1. 标题区
Column() {
Text('欢迎回来')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.text_primary'))
.width('100%');
Text('登录徒步迹,开始你的徒步之旅')
.fontSize(15)
.fontColor($r('app.color.text_secondary'))
.width('100%')
.margin({ top: 8 });
}
.width('100%')
.padding({ top: 60, bottom: 40 })
.alignItems(HorizontalAlign.Start);
// 2. 表单区
// 手机号
TextInput({ placeholder: '请输入手机号', text: this.phone })
.width('100%')
.height(50)
.backgroundColor($r('app.color.background_color'))
.borderRadius(12)
.padding({ left: 16 })
.type(InputType.PhoneNumber)
.maxLength(11)
.onChange((value: string) => {
this.phone = value;
this.errorMsg = '';
});
// 密码(带显示/隐藏切换)
Row() {
TextInput({ placeholder: '请输入密码', text: this.password })
.layoutWeight(1)
.backgroundColor(Color.Transparent)
.type(this.showPassword ? InputType.Normal : InputType.Password)
.onChange((value: string) => {
this.password = value;
this.errorMsg = '';
});
// 密码可见切换
Text(this.showPassword ? '🙈' : '👁️')
.fontSize(20)
.margin({ right: 16 })
.onClick(() => {
this.showPassword = !this.showPassword;
});
}
.width('100%').height(50)
.backgroundColor($r('app.color.background_color'))
.borderRadius(12)
.margin({ top: 16 });
// 错误提示
if (this.errorMsg) {
Text(this.errorMsg)
.fontSize(13)
.fontColor($r('app.color.error_color'))
.width('100%')
.margin({ top: 8 });
}
// 忘记密码
Text('忘记密码?')
.fontSize(14)
.fontColor($r('app.color.primary_color'))
.width('100%')
.textAlign(TextAlign.End)
.margin({ top: 12 });
// 3. 登录按钮
Button() {
if (this.isLoading) {
LoadingProgress().width(24).height(24).color(Color.White);
} else {
Text('登录').fontSize(16).fontColor(Color.White);
}
}
.width('100%').height(50)
.backgroundColor($r('app.color.primary_color'))
.borderRadius(25)
.margin({ top: 32 })
.enabled(this.isFormValid() && !this.isLoading)
.onClick(() => this.handleLogin());
// 注册入口
Row() {
Text('还没有账号?').fontSize(14).fontColor('#999');
Text('立即注册')
.fontSize(14)
.fontColor($r('app.color.primary_color'))
.onClick(() => {
router.pushUrl({ url: 'pages/RegisterPage' });
});
}
.margin({ top: 24 })
.justifyContent(FlexAlign.Center);
}
.width('100%').height('100%')
.padding({ left: 24, right: 24 })
.backgroundColor(Color.White);
}
// 表单校验
isFormValid(): boolean {
return this.phone.length === 11 && this.password.length >= 6;
}
// 登录逻辑
handleLogin(): void {
// 前端校验
if (!/^1[3-9]\d{9}$/.test(this.phone)) {
this.errorMsg = '请输入正确的手机号';
return;
}
if (this.password.length < 6) {
this.errorMsg = '密码至少6位';
return;
}
this.isLoading = true;
// 模拟登录请求
setTimeout(() => {
this.isLoading = false;
// 登录成功,保存 token
AppStorage.setOrCreate('isLogged', true);
router.replaceUrl({ url: 'pages/HomePage' });
}, 1500);
}
}
三、表单校验最佳实践
3.1 手机号格式校验
function validatePhone(phone: string): boolean {
return /^1[3-9]\d{9}$/.test(phone);
}
function validatePassword(password: string): { valid: boolean; msg: string } {
if (password.length < 6) {
return { valid: false, msg: '密码至少6位' };
}
if (!/[A-Za-z]/.test(password)) {
return { valid: false, msg: '密码需包含字母' };
}
if (!/\d/.test(password)) {
return { valid: false, msg: '密码需包含数字' };
}
return { valid: true, msg: '' };
}
3.2 实时校验
使用 @Watch 监听输入变化,实时校验:
@Component
struct FormField {
@State @Watch('validate') value: string = '';
@State error: string = '';
@Prop label: string = '';
@Prop rules: ((v: string) => string | null)[] = [];
validate(): void {
for (let rule of this.rules) {
const err = rule(this.value);
if (err) {
this.error = err;
return;
}
}
this.error = '';
}
build() {
Column() {
TextInput({ placeholder: `请输入${this.label}`, text: this.value })
.onChange((v) => { this.value = v; });
if (this.error) {
Text(this.error).fontSize(12).fontColor('#F44336');
}
}
}
}
四、用户体验优化
4.1 Loading 状态
登录按钮在请求中禁用并显示加载动画:
Button() {
if (this.isLoading) {
LoadingProgress().width(24).height(24).color(Color.White);
} else {
Text('登录').fontSize(16).fontColor(Color.White);
}
}
.enabled(!this.isLoading && this.isFormValid())
4.2 键盘处理
// 点击空白区域收起键盘
Column()
.onClick(() => {
inputMethod.getController()?.stopInputSession();
})
4.3 验证码倒计时
@State countdown: number = 0;
startCountdown(): void {
this.countdown = 60;
const interval = setInterval(() => {
this.countdown--;
if (this.countdown <= 0) {
clearInterval(interval);
}
}, 1000);
}
五、数据流说明
用户输入
↓
表单校验 ← @Watch 实时监听
↓ 通过
调用 API
↓
保存 Token → AppStorage
↓
更新登录状态 → @Provide('isLogged')
↓
路由跳转 → HomePage
六、总结
登录注册页面是 App 的基础功能。本文实现了一个包含完整校验和交互反馈的登录页,表单校验、Loading 状态、密码可见切换等交互都能直接用于“徒步迹“ App。
下一篇文章将实现验证码登录和忘记密码功能。
下一篇预告:鸿蒙原生开发手记:徒步迹 - 验证码登录与忘记密码
更多推荐




所有评论(0)