关于客户端表单验证和框架
Interaction Design 博客上有一篇关于 客户端表单验证 的好文章。它描述了在构建自己的客户端验证框架时需要注意的重要事项。
当然,构建自己的框架的另一种选择是使用 现有的框架。这种方法有一些重要的优势,其中包括“足够多的眼球,所有的错误都很浅”原则。
让我们看看验证插件在文章中列出的要点上的表现如何
1. 使用表单验证框架或表单验证库
检查。
2. 专注于解决重大验证问题
一旦你开始开发和实现你的验证,很容易尝试解决所有类型输入所需的潜在验证。我的建议是尝试在前端验证中捕获 75-85% 的潜在用户输入错误。试图捕获所有错误会导致以下问题
- 代码膨胀,你的框架会变得太大
- 测试客户端验证几乎不可能,因为存在太多可能出错的验证组合
- 业务规则将转移到前端。(稍后将介绍如何使用 Ajax 避免这种情况)
好吧,代码膨胀是我试图通过大量重构来解决的一个问题。当前的代码库有 1446 行(大约一半是内联文档)。几周前,Dan G. Switzer 查看了这个插件,并能够在几个小时内对特定的代码相关问题提供极好的帮助。
关于测试:验证插件的当前测试套件运行 65 个测试,包含 350 多个断言。jQuery 的测试套件运行大约 500 个断言。我似乎拥有良好的代码覆盖率,因为我尽可能为所有出现的错误添加了测试。回归问题很可能被测试套件捕获,并且它在开发过程中也提供了很大的帮助。
测试浏览器事件和 AJAX 仍然是一项非常困难的任务,即使使用 jQuery 测试套件中的 AJAX 支持也是如此。
关于业务规则转移到前端:这更多是一个设计和架构问题。即将发布的 1.2 版本将支持使用 AJAX 避免这种情况。
3. 在提交表单之前进行表单验证
这里的意思是在用户输入内容时进行验证,而不是等到提交事件。1.0 之前的版本允许你指定一个事件来检查单个元素,例如 blur 或 keyup。这在某些情况下有效,但在其他情况下却令人不安,例如用户点击一个输入框,却被一个烦人的错误消息所迎接。为了解决这些问题,1.1 版本发布了一个更复杂的系统。基本上,插件会在用户离开一个输入了不完整内容的字段时等待验证。如果该字段已被标记为无效(例如,在尝试提交无效表单后),所有元素都会在 keyup(文本输入)或 click(复选框、单选按钮)时进行验证。当前的实现还不是完美,当然,欢迎反馈。
4. 使用 Ajax 表单验证来验证业务数据输入
1.2 版本中的 AJAX 验证的预告
$("#myform").validate({
rules: {
username: {
required: true,
minLength: 2,
remote: "users.php"
}
},
messages: {
username: {
required: "Enter your username",
minLength: "At least 2 characters are necessary",
remote: String.format("The name {0} is already in use")
}
}
});
API 允许你使用与本地验证相同的声明式风格来进行远程验证。String.format
创建另一个函数,该函数稍后会使用用户输入的值进行调用,从而生成类似“名称 asdf 已存在”的错误消息。
查看 AJAX 验证预览 以获取更多详细信息。
5. 对你的 JavaScript 表单验证进行大量测试
这在 上面 已经讨论过了。
6. 将输入数据重写为有效的格式
现在这是一个有趣的观点。基本的想法是接受“20070515”作为有效的日期,将其转换为“2007-05-15”进行验证。我还没有看到任何针对此类功能的具体请求,因此如果有任何人感兴趣,请告诉我。同时,一个好主意可能是使用 掩码输入插件 来帮助用户输入正确的格式。
7. 在设计过程的后期添加 JavaScript 表单验证
这是一个非常好的建议。由于 jQuery 的非侵入性,它在这方面提供了很大的帮助。完全不使用 JavaScript 设计你的表单,并在之后添加它,尽可能地改善用户体验(UX)。
8. 使脚本与 i18n 和 l10n 兼容
换句话说:避免硬编码字符串,而是尽可能地使其易于用当前区域设置替换它们。
验证插件允许你通过覆盖所有默认消息来翻译它们。只需在插件文件之后包含一个文件,其中包含以下内容
$.extend($.validator.messages, {
required: "Eingabe nötig",
email: "Bitte eine gültige E-Mail-Adresse eingeben",
...
});
这种方法效果很好。你可以在同一个文件中收集其他翻译,例如 日期选择器 的标签。
然后,包含适合用户区域设置的正确翻译文件仅仅是一个服务器端问题。
其他问题,例如不同的数字或日期格式,可以通过编写自定义方法或覆盖默认方法(在 $.validator.methods 中)来解决。默认情况下提供了德语日期和数字格式的方法:date(默认的 JavaScript Date 格式)、dateISO(1990-01-01 或 1990/01/01)、dateDE(01.01.1990 或 2.12.2012)以及 number(100,000.59)和 numberDE(100.000,59)。但是,目前这些方法都没有验证任何范围,例如 0001-13-50 也是一个有效的 ISO 日期。
9. 向验证框架添加回调函数
验证插件提供的最重要的回调函数是 submitHandler
。当提交一个有效表单时,会调用它,允许你例如通过 AJAX 提交表单。其他可用的回调函数包括 errorPlacement
,用于自定义错误消息插入 DOM 的位置,例如表格布局。
在 1.2 版本中,添加了一个针对无效表单的回调函数,该函数在用户提交表单且表单无效时每次都会被调用。到目前为止,showErrors
回调函数可以用于此目的,但它也会在每次验证单个元素时被调用。新的回调函数可以用来更新一条消息,例如“表单中存在 6 个问题”。显示和隐藏这样的消息可以使用现有的 errorContainer
选项进行处理。
10. 使你的框架/库可扩展
使用自己的东西扩展验证插件最重要的点是 $.validator.addMethod
。它允许你添加任何所需的验证方法。通过将你自己的自定义方法保存在你自己的文件中,很容易更新插件本身。
AJAX 验证的第一种方法很可能会演变成 $.validator.addRemoteMethod
,它提供了远程 AJAX 方法所需的所有样板代码,但允许你使用任何所需的协议。无论你是使用 get 还是 post、发送单个值还是将整个表单发送到服务器,以及服务器是否仅返回 true 或 false 或者返回一个要显示的错误消息,无论你更喜欢或需要使用什么格式,这都无关紧要。当然,实现该方法需要更多工作,但它提供了很大的灵活性。你对这方面的反馈至关重要,因为我不会随意猜测你可能需要什么。
我希望这能让你了解当前表单验证的状态及其进展,并能帮助你决定是否使用它。
一个可用性方面的考虑是选择何时进行验证。在你的示例中,似乎出现了不同的场景
– 用户更改字段
– 用户更正无效字段
– 用户提交表单
从用户的角度来看,如果一个字段无效,他必须返回到该字段。这让我得出结论,如果该字段无效且在之前没有被验证,那么浏览器应该能够以某种方式取消焦点更改。用户必须能够在收到通知后更改焦点。
请注意,某些信息无法通过 AJAX 进行验证,因为法律原因,例如社会安全号码、电子邮件或其他敏感的个人数据,因为你是在没有用户请求(以及适当的建议)的情况下发送信息(当然是不加密的,它是纯 AJAX)。
我一直致力于开发一个类似的框架,它注重可扩展性,最近它还遇到了一个最具压力性的用例,我需要为可拖动元素添加自定义验证并扩展提供给用户的视觉反馈(详细的错误消息和黄色淡出),此外,我需要在提交表单时通过 AJAX 验证一个值以避免重复……幸运的是,我的初始设计具有足够的通用性,可以提供完全的外部可扩展性(在我的情况下,使用 Mootools 完成),同时保持原始的库无关源代码不受影响。
很高兴看到越来越多的开发人员选择可扩展的路径,尤其是在 JavaScript 的一些不太成熟的领域,例如客户端表单验证,因为我们总是有新的需求需要满足。
/gonchuki
@gonchuki
如果你处理的是社保号码等数据,我假设你的网站是为企业或其他可以负担 SSL 证书的组织服务的。 除非我遗漏了什么,否则我认为 Ajax 可以像普通请求一样通过加密连接工作。 但是,我从未尝试过,所以可能错了。
然而,如果使用 onblur 或其他自动化方法,你仍然在未经用户请求的情况下传输敏感的个人信息。
这只是为了让每个人在处理通过 AJAX 进行的“客户端”验证时都能妥善处理,该脚本的作者在其文档中没有说明这一点,而且给出一些建议总是没有坏处的。 请记住,并非所有人都清楚处理敏感个人信息的法律问题,甚至可能不关心获得 SSL 证书(我知道这是一件坏事,但有时客户甚至托管提供商可能是你获得适当 SSL 证书的最大障碍)。
@zimbatm: 到目前为止,我的结论是,只有在用户提交表单时,程序化的焦点改变才有用。
@gonchuki: 感谢你提到这一点。 尽管该框架本身对此无能为力,除了在文档中提到该问题之外。 我将在为 1.2 版本更新文档时牢记这一点。
正如你提到的,你一直在开发的框架:你能分享一些关于它的信息吗?
很棒的帖子。 我投票支持
“6. 将输入数据重写为有效格式”
参数“event”无法执行任何操作。 它有三个选项(blur、keyup、default),当我更改它时,我看不到任何更改。 有人能告诉我为什么吗?
Pingback: jQuery:关于客户端表单验证和框架 « Williamo 的博客。