文章目录

前言
做表单就绕不开验证。用户名不能为空、邮箱要有 @ 符号、手机号得是 11 位数字------这些规则看起来简单,但真正做到用户体验好的验证逻辑,还是有不少细节要处理。
今天我用 ArkUI 从零搭建一个带实时验证的表单,三个字段(用户名、邮箱、手机号),边输入边校验,出错了输入框变红、下方显示错误提示,点提交时再做一次全量检查。
反面教材
先看看新手容易犯的错误------不做实时验证,只在提交时统一检查:
typescript
// 反面教材:只在提交时验证
Button('提交').onClick(() => {
if (!this.username) {
AlertDialog.show({ message: '用户名不能为空' })
return
}
if (!this.email.includes('@')) {
AlertDialog.show({ message: '邮箱格式不对' })
return
}
// ... 一个一个弹 Dialog,用户烦死了
})

这种做法的问题很明显:
- 用户填完所有字段点提交,才知道第一个字段就错了
- 每次只提示一个错误,改完再提交又报另一个错
- 用 AlertDialog 弹提示太重了,打断操作流程
正确姿势
正确的验证方式是这样的:
- 实时验证 --- 用户输入时立即检查,在输入框下方显示错误
- 视觉反馈 --- 出错的输入框边框变红,一眼就能看到
- 提交时全量检查 --- 点提交时再扫一遍,确保没有遗漏
原理解析

验证状态管理
每个字段需要两个状态变量:一个存值,一个存错误信息。
typescript
@State username: string = ''
@State email: string = ''
@State phone: string = ''
@State usernameError: string = ''
@State emailError: string = ''
@State phoneError: string = ''
错误信息为空字符串表示没有错误,有内容就显示对应的错误提示。
输入框 + 实时验证
以用户名为例:
typescript
Column() {
Text('用户名').fontSize(13).fontColor('#999999').margin({ bottom: 6 })
TextInput({ placeholder: '请输入用户名(至少3个字符)' })
.width('100%').height(42)
.borderColor(this.usernameError ? '#FF6B6B' : '#E0E0E0')
.onChange((value: string) => {
this.username = value
this.usernameError = value.length > 0 && value.length < 3
? '用户名至少需要3个字符' : ''
})
if (this.usernameError) {
Text(this.usernameError)
.fontSize(11).fontColor('#FF6B6B').margin({ top: 4 })
}
}
.width('100%').margin({ bottom: 16 })
三个关键点:
borderColor动态切换 --- 有错误时红色,没错误时灰色onChange里做校验 --- 输入长度大于 0 但小于 3 时设置错误信息;长度为 0 时清空错误(用户还没开始输呢,别急着报错)- 条件渲染错误文本 --- 用
if (this.usernameError)控制错误提示的显示
邮箱验证
typescript
TextInput({ placeholder: '请输入邮箱地址' })
.width('100%').height(42)
.borderColor(this.emailError ? '#FF6B6B' : '#E0E0E0')
.onChange((value: string) => {
this.email = value
if (value.length > 0 && !value.includes('@')) {
this.emailError = '请输入有效的邮箱地址'
} else {
this.emailError = ''
}
})
邮箱验证用了最简单的判断------有没有 @ 符号。实际项目中可以用正则表达式做更严格的检查。
手机号验证
typescript
TextInput({ placeholder: '请输入11位手机号' })
.width('100%').height(42)
.borderColor(this.phoneError ? '#FF6B6B' : '#E0E0E0')
.type(InputType.Number)
.onChange((value: string) => {
this.phone = value
if (value.length > 0 && value.length < 11) {
this.phoneError = '手机号需要11位数字'
} else {
this.phoneError = ''
}
})
手机号用了 InputType.Number 限制只能输入数字,然后检查长度是不是 11 位。
提交按钮的全量验证
typescript
Button('验证提交')
.width('100%').height(44)
.backgroundColor('#4D96FF').borderRadius(10)
.fontColor('#FFFFFF').fontSize(15)
.margin({ top: 16 })
.onClick(() => {
let hasError = false
if (!this.username) {
this.usernameError = '请输入用户名'; hasError = true
}
if (!this.email) {
this.emailError = '请输入邮箱'; hasError = true
}
if (!this.phone) {
this.phoneError = '请输入手机号'; hasError = true
}
if (!hasError && !this.usernameError
&& !this.emailError && !this.phoneError) {
AlertDialog.show({
title: '验证通过',
message: '所有字段验证通过!',
confirm: { value: '确定', action: () => {} }
})
}
})
提交时做两件事:
- 检查每个字段是否为空,空的就设置错误信息
- 如果没有任何错误(包括实时验证的错误),才允许提交
实践清单
实现表单验证时,按这个清单来检查你的代码:
- 每个字段有独立的状态变量和错误变量
-
onChange里做实时验证 - 输入框的
borderColor根据错误状态切换 - 错误文本用条件渲染,有错误才显示
- 提交按钮里做全量验证(包括空值检查和格式检查)
- 错误文本的字号比正常文本小(11-12px)
- 错误颜色统一用红色(推荐
#FF6B6B或#E74C3C)
检查表格
| 验证规则 | 实现位置 | 触发时机 |
|---|---|---|
| 非空检查 | 提交时 | 点击提交按钮 |
| 最小长度 | onChange | 每次输入 |
| 格式检查(邮箱) | onChange | 每次输入 |
| 长度检查(手机号) | onChange | 每次输入 |
写在最后
表单验证的核心原则是"尽早发现、即时反馈"。别让用户填了一大堆才发现第一个字段就错了,也别在用户还没开始输的时候就报红。
这套"实时验证 + 提交全量检查"的方案适用于绝大多数表单场景。验证规则复杂的话,可以把验证逻辑抽成独立的函数,代码会更清晰。