这个表单打死我也不填!
本文为掘金社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
前言
表单在应用内随处可见,注册、登录、完善个人资料、发表内容……在 B 端应用中,表单操作更是员工日常工作中使用最多的功能。好的表单体验能够让用户更加轻松地完成信息录入,从而让我们获知更多用户的信息、在应用内产生更多内容或者让员工的工作更为轻松。糟糕的表单,则会让用户感到绝望,有一种打死也不想填的感觉!那么,对于开发而言,如何提高表单操作的用户体验?本篇我们就来讲讲常见的提高表单用户体验的方式,推荐在封装表单组件的时候将这些因素考虑进去,形成公司内统一的规范,保持体验的一致性。
错误提示
表单输入不可避免会出错,及时、准确地给出错误提示能够让用户快速更正错误,提高表单录入的效率。错误提示有以下三种方式:
- 内联提示:当输入完成后,立即校验表单内容并给出错误提示;
- 提交时客户端提示:输入完成后,点击提交按钮时对整个表单进行错误校验和提示;
- 提交后服务端校验:提交到后端后,有服务端应用对表单进行校验。
对于输入表单内容较少的错误提示,推荐采用内联的方式实现。内联方式的错误提示就是将错误信息直接显示在表单附近(通常是下方),这样用户更容易察觉。我们来看看在 Flutter 中如何实现内联的错误提示。
Flutter 的TextField
组件有一个 decoration
属性,类型为InputDecoration
。通过 InputDecoration
类的errorText
和errorStyle
可以构建一个 Text
组件,当 errorText
不为空时就会默认在 TextField
下方显示错误指示,从而提示用户输入有误,示例代码和运行结果如下。需要注意的是,错误提示信息应该准确,避免泛泛的错误提示。我曾经遇到过的反面例子就是产品没有明确错误提示(很多产品因为见过不少标准的错误提示,就默认开发也知道如何提示错误,所以文档并不会给出错误提示文案),然后开发直接粗暴地显示一个“输入有误”的标准提示。
TextField(
autofocus: true,
decoration: InputDecoration(
label: const Text('邮箱'),
hintText: '请输入电子邮箱地址',
errorText: _errorText,
errorStyle: TextStyle(color: Colors.red[400], fontSize: 14.0),
),
onEditingComplete: () {
if (!FormUtils.isValidEmail(_email)) {
setState(() {
_errorText = '请输入正确的邮箱地址';
});
} else {
setState(() {
_errorText = null;
});
}
},
onChanged: (text) {
_email = text;
},
)
对于表单录入内容较多的情况来说,推荐使用提交时进行错误校验和提示。因为表单内容较多时,通常用户更希望专注输入内容,如果经常给出错误提示会转移用户注意力,打断用户填写表单的思路。
标签
表单的标签有三种,顶部标签、左侧标签和浮动标签,当然简洁的设计有时候会使用图标替代标签文字。研究表明,顶部标签的方式填写表单的效率更高,因为一路向下填写即可,视线不需要实现 Z 字形路线移动,但是顶部标签相对来说比较占空间,在移动端不太多见。大多数国外的应用顶部标签居多,例如下面是亚马逊的登录界面。 gmail 则别出新裁地在默认的时候省去了标签,一旦聚焦标签显示在输入框的上边框,可以说是将效率和空间做了充分的利用(这种效果在 Flutter 中默认就有,只要TextField 制定了边框,就会在聚焦后将标签显示在边框上)。
在 Flutter 中,就如同我们上面的例子那样,默认标签是不可见的,聚焦后才会以小字的形式显示上面的标签。我们来看看 Flutter 文本输入框的标签具体如何设置。Flutter 为设置标签样式和交互提供了3个属性:
labelStyle
:TextStyle
对象,用于设置默认的标签样式。floatingLabelStyle
:设置浮动状态(即标签在输入框上方)时的标签状态,这个属性可以是TextStyle
对象也可以是MaterialStateTextStyle
对象,如果是MaterialStateTextStyle
对象的话,就可以设置不同状态下的标签样式,比如错误、聚焦和光标移入等。floatingLabelBehavior
:设置浮动标签的交互行为,默认是auto
,即聚焦的时候才显示,也可以设置为never
不显示标签,或者设置为always
一直显示标签。
下面是对应的代码,我们来看看不同形式的区别:
Column(
children: [
TextField(
autofocus: true,
decoration: InputDecoration(
label: const Text('邮箱'),
hintText: '请输入电子邮箱地址',
floatingLabelStyle: MaterialStateTextStyle.resolveWith(
(Set<MaterialState> states) {
final Color color;
if (states.contains(MaterialState.error)) {
color = Colors.red[400]!;
} else if (states.contains(MaterialState.focused)) {
color = Colors.blue[400]!;
} else {
color = Colors.black54;
}
return TextStyle(
color: color,
);
}),
floatingLabelBehavior: FloatingLabelBehavior.always,
errorText: _errorText,
errorStyle: TextStyle(color: Colors.red[400], fontSize: 14.0),
),
onEditingComplete: () {
if (!FormUtils.isValidEmail(_email)) {
setState(() {
_errorText = '请输入正确的邮箱地址';
});
} else {
setState(() {
_errorText = null;
});
}
},
onChanged: (text) {
_email = text;
},
),
TextField(
decoration: InputDecoration(
label: const Text('密码'),
hintText: '请输入密码',
floatingLabelBehavior: FloatingLabelBehavior.auto,
),
obscureText: true,
),
TextField(
decoration: InputDecoration(
label: const Text('确认密码'),
hintText: '请再次输入密码',
floatingLabelBehavior: FloatingLabelBehavior.never,
),
obscureText: true,
),
],
),
- 第一个表单邮箱我们使用了固定显示标签的形式,同时通过
floatingLabelStyle
设置了不同状态的标签颜色; - 第二个表单密码我们使用了
auto
模式,可以看到标签一开始是在表单行内的,聚焦后标签移到了输入框上方,而输入框会展示占位文字; - 第三个确认密码我们使用了
never
模式,标签一开始是在表单行内的,聚焦后标签移到了输入框上方,而输入框会展示占位文字,但标签会消失不见。
从体验上来说,第一种和第二种会更好些,不过在国内大部分是直接将标签省略或者使用左侧标签。下面是阿里云的注册界面,没有标签的表单适用于表单项较少的场景。
对于 Flutter 的
TextField
,如果要使用左侧标签,则需要自定义实现(可以参考之前的文章:)。这里需要注意,虽然 TextField
提供了一个 prefix
可以自定义前置组件,但是这个组件只会在文本框聚焦的时候才显示。
键盘
键盘处理在手机端非常常见了,建议根据输入类型来设置键盘类型,常见的键盘类型和用途如下:
TextInputType.number
:输入数字,带小数点;TextInputType.phone
:输入数字,*和#字符,适合拨打电话或输入号码;TextInputType.email
:输入电子邮箱地址;TextInputType.url
:适合输入链接地址,会默认显示/和.字符;TextInputType.multiline
:适合多行输入,带有回车符,回车后自动换行;
需要注意的是,安卓和 iOS 的键盘会有些区别,具体可以看看 TextInputType
的各个枚举值的说明。
表单项过多
当要录入的表单项很多的时候,如果表单没有条理性,会让用户望而生畏,忍受力强的用户发发闹骚,无法忍受的用户直接放弃。比如下面这样的注册表单,看到就会绝望,打死我也不会填的。
怎么处理表单项过多?推荐的做法有三种:
- 表单分组:比如将必填的表单分为一组,其他选填的表单分为一组;这种在 PC 端会更适用。
- 分步骤填写:还是表单分组,但是分多个步骤,每页展示的表单数量少,不会让用户一下子感觉要填很多东西。而且,从心理学上来说,前面填了一部分会让用户积累沉没成本,后面的表单会更愿意填。同时,对于非必填的分组提供跳过选项。
- 利用时间差:也就是一开始的时候让用户只填很少的信息,然后在之后的使用过程中逐步引导用户完善其他资料。比如在领英里,每次就会让我们填写一点点信息,最终将个人信息收集完整。
表单校验
前面错误提示的时候,已经讲过一些校验的内容了。这里要说的是,我们开发一定要养成对表单进行校验的习惯。本人就遇到过这样的情况,产品没有特别说明校验规则,然后前后端都不校验,结果录入的数据导致各种各样的 bug。这种写 bug 的行为会极大降低我们程序员的段位!对于校验,建议是在内部形成统一的默认规则,比如下面几点:
- 文本输入的最大输入长度限制;
- 数值的最大输入范围;
- 小数默认保留的位数;
- 常用类型数据的校验规则统一,例如姓名、邮箱、手机号、身份证号、经纬度、日期、企业统一社会信用代码,密码强度、金额等。避免前后端校验规则不一致。
至于什么时候校验,建议是按表单数量来定,表单数量少可以在输入完成后进行校验;表单数量多推荐是在完成输入后整体校验。同时,前端务必保证提交给后端数据的基本合法性(除了需要后端通过业务逻辑校验的除外,例如唯一性检查,是否存在检查等)。
总结
如果评估一个前端开发做事情的细致程度,通常会通过他写的表单业务来评估。基本上,测试一遍表单的输入交互、错误验证就能够判断出来。一个好的前端,即便是产品不说,也会按照规范将交互和基本的校验做好。同时,保持与产品的沟通也很重要,如果对表单的校验规则有疑惑,那一定是需要二次确认的。虽然不确认锅可以甩给产品,但是 bug 却是留在自己头上的。
转载自:https://juejin.cn/post/7155834693504466952