平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“基于HarmonyOS的表单与校验功能(输入验证与正则表达式)”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。


结合项目来看,表单是应用收集用户信息的主要方式。无论是登录注册、个人信息填写、搜索筛选,还是设置设置,都离不开表单组件。而表单的核心挑战是数据校验——如何确保用户输入的数据格式正确、内容合法。
从实现思路看,HarmonyOS ArkUI 提供了丰富的表单组件(TextInput、TextArea、Checkbox、Radio、Switch 等),结合正则表达式能够完成强大的数据校验能力。本文将以一个清爽蓝白风格的表单页面为主线,深入讲解表单开发与数据校验的核心技能。
| 组件 | 用途 | 关键属性 |
|---|---|---|
| TextInput | 单行文本输入 | type、placeholder |
| TextArea | 多行文本输入 | placeholder、maxLength |
| Search | 搜索输入 | hint、searchButton |
| PasswordInput | 密码输入 | showPasswordIcon |
| 组件 | 用途 | 关键属性 |
|---|---|---|
| Checkbox | 复选 | select、selectedColor |
| Radio | 单选 | value、checked |
| Switch | 开关 | isOn、selectedColor |
| Slider | 滑块 | min、max、value |
| DatePicker | 日期选择 | start、end |
| 组件 | 用途 |
|---|---|
| Button | 普通按钮 |
| LoadingProgress | 加载按钮 |
TextInput({ placeholder: '请输入用户名', text: this.username })
.width('100%')
.height(46)
.onChange((v: string) => {
this.username = v;
})代码说明:
TextInput 构造参数:placeholder 占位提示,text 绑定当前值。.onChange 回调:输入内容变化时触发,参数是当前输入值。TextInput({ placeholder: '邮箱' })
.type(InputType.Email) // 邮箱键盘
TextInput({ placeholder: '手机号' })
.type(InputType.PhoneNumber) // 数字键盘
TextInput({ placeholder: '密码' })
.type(InputType.Password) // 密码输入
TextInput({ placeholder: '数字' })
.type(InputType.Number) // 数字键盘代码说明:
type 属性控制键盘类型和输入限制:
InputType.Email:邮箱键盘,带 @ 符号。InputType.PhoneNumber:数字键盘。InputType.Password:密码输入,内容显示。InputType.Number:纯数字键盘。TextInput({ placeholder: '输入' })
.maxLength(20) // 最大长度
.enabled(true) // 是否可用
.showCounter(true) // 显示字数统计
.enterKeyType(EnterKeyType.Done) // 回车键类型
.onSubmit(() => { // 提交回调
console.info('提交');
})
落到代码里,正则表达式(Regular Expression)是一种描述字符串匹配模式的工具。它用特殊的语法定义"什么样的字符串是合法的",随后用来校验、搜索、替换文本。
| 模式 | 含义 | 示例 |
|---|---|---|
^...$ | 匹配整个字符串 | ^abc$ 匹配 “abc” |
d | 数字 | d{11} 匹配 11 位数字 |
w | 字母/数字/下划线 | w+ 匹配单词 |
[a-z] | 小写字母 | [a-z]+ |
[0-9] | 数字 | [0-9]{3} |
{n,m} | 重复 n 到 m 次 | {3,12} |
+ | 至少 1 次 | d+ |
* | 0 次或多次 | w* |
? | 0 次或 1 次 | a? |
| ` | ` | 或 |
(?=...) | 正向预查 | (?=.*d) 必须含数字 |
// 用户名:3-12 位字母/数字/下划线
const usernameRegex = /^[a-zA-Z0-9_]{3,12}$/;
// 邮箱
const emailRegex = /^[w.-]+@[w-]+(.[w-]+)+$/;
// 手机号:11 位大陆手机号
const phoneRegex = /^1[3-9]d{9}$/;
// 密码:6-16 位,必须包含字母和数字
const passwordRegex = /^(?=.*[A-Za-z])(?=.*d)[A-Za-zd]{6,16}$/;
// 身分证号
const idCardRegex = /^d{17}[dXx]$/;
// URL
const urlRegex = /^(https?|ftp)://[^s/$.?#].[^s]*$/;
代码说明:
^ 和 $ 锚定字符串的开始和结束,确保整个字符串匹配。(?=.*[A-Za-z]) 是正向预查,表示"后面必须包含字母"。(?=.*d) 表示"后面必须包含数字"。理解这一步时,下面我们实现一个完整的表单校验页面,包含用户名、邮箱、手机号、密码四个字段的实时校验。
interface RuleRow {
field: string;
rule: string;
example: string;
}
代码说明:
RuleRow 接口描述校验规则表格中的一行数据,包含字段名、规则和示例。
@Entry
@Component
struct FormPage {
@State username: string = '';
@State email: string = '';
@State phone: string = '';
@State password: string = '';
@State usernameErr: string = '';
@State emailErr: string = '';
@State phoneErr: string = '';
@State passwordErr: string = '';
@State rules: RuleRow[] = [
{ field: '用户名', rule: '3-12 位字母/数字/下划线', example: 'atom_code' },
{ field: '邮箱', rule: '标准邮箱格式', example: '[email protected]' },
{ field: '手机号', rule: '11 位大陆手机号', example: '13800138000' },
{ field: '密码', rule: '6-16 位含字母和数字', example: 'abc123' }
];
代码说明:
rules 数组存储校验规则表格数据。validateUsername(v: string): void {
this.username = v;
this.usernameErr = /^[a-zA-Z0-9_]{3,12}$/.test(v) ? '' : '用户名需 3-12 位字母/数字/下划线';
}
validateEmail(v: string): void {
this.email = v;
this.emailErr = /^[w.-]+@[w-]+(.[w-]+)+$/.test(v) ? '' : '邮箱格式不正确';
}
validatePhone(v: string): void {
this.phone = v;
this.phoneErr = /^1[3-9]d{9}$/.test(v) ? '' : '手机号格式不正确';
}
validatePassword(v: string): void {
this.password = v;
this.passwordErr = /^(?=.*[A-Za-z])(?=.*d)[A-Za-zd]{6,16}$/.test(v) ? '' : '密码需 6-16 位且包含字母和数字';
}代码说明:
四个校验方法结构一致,核心逻辑是:
this.username = v 将输入值保存到状态。.test(v) 方法测试输入值是否匹配正则表达式,得到布尔值。onChange 回调中调用,实现输入即校验的实时反馈。submit(): void {
this.validateUsername(this.username);
this.validateEmail(this.email);
this.validatePhone(this.phone);
this.validatePassword(this.password);
const ok = !this.usernameErr && !this.emailErr && !this.phoneErr && !this.passwordErr;
if (ok) {
promptAction.showToast({ message: '✓ 校验通过,提交成功' });
} else {
promptAction.showToast({ message: '✗ 存在校验错误,请检查' });
}
}
代码说明:
submit 方法在点击提交按钮时执行:
@Builder
FormField(label: string, placeholder: string, value: string, error: string, onInput: (v: string) => void) {
Column({ space: 6 }) {
Text(label)
.fontSize(13)
.fontWeight(FontWeight.Medium)
.fontColor('#2F3542')
.alignSelf(ItemAlign.Start)
TextInput({ placeholder: placeholder, text: value })
.width('100%')
.height(46)
.backgroundColor('#F5F7FA')
.borderRadius(10)
.placeholderColor('#A0A8B4')
.border({ width: 1, color: error ? '#FF4757' : '#E1E6ED' })
.onChange((v: string) => { onInput(v); })
Text(error)
.fontSize(11)
.fontColor('#FF4757')
.alignSelf(ItemAlign.Start)
.height(16)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
}
代码说明:
FormField 是表单字段的通用构建器,借助参数化实现复用:
label:字段标签。placeholder:输入占位提示。value:当前输入值。error:错误信息。onInput:输入回调函数(作为参数传入)。.border({ width: 1, color: error ? '#FF4757' : '#E1E6ED' }) 根据是否有错误切换边框颜色,有错误显示红色边框。Text(error) 显示错误信息,.height(16) 固定高度,即使无错误也占位,避免布局跳动。onInput 参数是函数类型,在 onChange 中调用,实现了构建器的通用性。build() {
Scroll() {
Column({ space: 16 }) {
// 顶部标题
Column() {
Text('FORM')
.fontSize(12)
.fontColor('#B3D4FF')
.letterSpacing(8)
Text('表单与校验')
.fontSize(26)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.margin({ top: 6 })
Text('正则表达式 · 实时校验')
.fontSize(12)
.fontColor('#B3D4FF')
.margin({ top: 6 })
}
.width('100%')
.padding({ top: 48, bottom: 30 })
.backgroundColor('#3B82F6')
// 表单区
Column({ space: 4 }) {
this.FormField('用户名', '请输入用户名', this.username, this.usernameErr, (v: string) => { this.validateUsername(v); })
this.FormField('邮箱', '请输入邮箱', this.email, this.emailErr, (v: string) => { this.validateEmail(v); })
this.FormField('手机号', '请输入手机号', this.phone, this.phoneErr, (v: string) => { this.validatePhone(v); })
this.FormField('密码', '请输入密码', this.password, this.passwordErr, (v: string) => { this.validatePassword(v); })
}
.width('100%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(16)
.shadow({ radius: 8, color: '#22000000', offsetY: 4 })
// 大号提交按钮
Button('提交表单')
.width('100%')
.height(52)
.fontSize(17)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.linearGradient({
angle: 90,
colors: [['#3B82F6', 0], ['#6366F1', 1]]
})
.borderRadius(26)
.shadow({ radius: 14, color: '#553B82F6', offsetY: 4 })
.onClick(() => { this.submit(); })代码说明:
表单区借助 FormField 构建器生成四个字段,每个字段传入对应的状态、错误信息和校验回调。提交按钮采用蓝紫渐变、大圆角,形成醒目的 CTA(行动召唤)按钮。
// 校验规则表格
Column() {
Text('校验规则速查')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#3B82F6')
.alignSelf(ItemAlign.Start)
.margin({ bottom: 8 })
Row() {
Text('字段').layoutWeight(1).fontSize(12).fontWeight(FontWeight.Bold).fontColor('#3B82F6')
Text('规则').layoutWeight(2).fontSize(12).fontWeight(FontWeight.Bold).fontColor('#3B82F6')
Text('示例').layoutWeight(1).fontSize(12).fontWeight(FontWeight.Bold).fontColor('#3B82F6')
}
.width('100%')
.padding(10)
.backgroundColor('#EFF6FF')
ForEach(this.rules, (row: RuleRow) => {
Row() {
Text(row.field).layoutWeight(1).fontSize(12).fontColor('#2F3542')
Text(row.rule).layoutWeight(2).fontSize(11).fontColor('#555555')
Text(row.example).layoutWeight(1).fontSize(11).fontColor('#3B82F6').fontFamily('monospace')
}
.width('100%')
.padding(10)
.border({ width: { bottom: 1 }, color: '#EFF6FF' })
})
}
.width('100%')
.padding(16)
.backgroundColor('#F8FBFF')
.borderRadius(14)
.border({ width: 1, color: '#DCE9FB' })
代码说明:
校验规则速查表是一个带表头的三列表格:
ForEach 渲染,示例列采用蓝色等宽字体。layoutWeight 控制(1:2:1)。正则表达式容易出错,建议先在测试工具中验证,再应用到代码中。
除了格式校验,还要处理必填字段的空值校验:
validateRequired(v: string): string {
if (!v.trim()) {
return '该字段不能为空';
}
return '';
}
原因:正则表达式错误,或 .test() 采用不当。
解决:先在测试工具验证正则,确认 .test() 参数正确。
原因:错误信息高度不固定,导致布局变化。
解决:给错误提示设置固定高度(如 .height(16))。
原因:没有设置 .type(InputType.Password)。
解决:设置密码输入类型。
结合项目来看,本文深入讲解了 HarmonyOS 表单与校验技术,借助一个清爽蓝白风格的表单页面实战演示了输入组件、正则校验、实时反馈和提交处理等核心能力。
核心要点回顾:
.test() 方法校验输入值。onChange 中触发,提交时统一验证。@Builder 参数化表单字段,实现复用。实际处理时,表单是收集用户信息的关键,掌握校验技术能构建可靠、友好的表单体验。下一篇我们将讲解 HarmonyOS 数据可视化(Canvas 绘图)。
到此这篇关于基于HarmonyOS的表单与校验功能(输入验证与正则表达式)的文章就介绍到这了,更多相关HarmonyOS表单与校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多兼容脚本之家!