表单数据校验
2026-08-08 04:50:31 福利中心不使用内建 API 时的表单校验
有时,例如使用旧版浏览器或自定义小部件,你将无法(或不希望)使用约束校验 API。在这种情况下,你仍然可以使用 JavaScript 来校验你的表单。校验表单比起真实数据校验更像是一个用户界面问题。
要校验表单,你必须问自己几个问题:
我应该进行什么样的校验?
你需要确定如何校验你的数据:字符串操作,类型转换,正则表达式等。这取决于你。只要记住,表单数据一般都是文本,并总是以字符串形式提供给脚本。
如果表单校验失败,我该怎么办?
这显然是一个 UI 问题。你必须决定表单的行为方式:表单是否发送数据?是否突出显示错误的字段?是否显示错误消息?
如何帮助用户纠正无效数据?
为了减少用户的挫折感,提供尽可能多的有用的信息是非常重要的,以便引导他们纠正他们的输入。你应该提供前期建议,以便他们知道预期的输入是什么以及明确的错误消息。如果你想深入了解表单校验用户界面要求,那么你应该阅读一些有用的文章:
SmashingMagazine: Form-Field Validation: The Errors-Only Approach
SmashingMagazine: Web Form Validation: Best Practices and Tutorials
Six Revision: Best Practices for Hints and Validation in Web Forms
A List Apart: Inline Validation in Web Forms
不使用约束校验 API 的例子
为了说明这一点,让我们重构一下前面的例子,以便它可以在旧版浏览器中使用:
html
正如你所看到的,HTML 几乎是一样的;我们只是关闭了 HTML 校验功能。请注意,ARIA 是与 HTML5 无关的独立规范。
CSS
同样的,CSS 也不需要太多的改动,我们只需将 :invalid 伪类变成真实的类,并避免使用不适用于 Internet Explorer 6 的属性选择器。
css/* 仅为了使示例更好看 */
body {
font: 1em sans-serif;
padding: 0;
margin: 0;
}
form {
max-width: 200px;
}
p * {
display: block;
}
input.mail {
-webkit-appearance: none;
width: 100%;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* 校验失败的元素样式 */
input.invalid {
border-color: #900;
background-color: #fdd;
}
input:focus.invalid {
outline: none;
}
/* 错误消息的样式 */
.error {
width: 100%;
padding: 0;
font-size: 80%;
color: white;
background-color: #900;
border-radius: 0 0 5px 5px;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.error.active {
padding: 0.3em;
}
JavaScript
JavaScript 代码有很大的变化,需要做更多的工作。
js// 使用旧版浏览器选择 DOM 节点的方法较少
var form = document.getElementsByTagName("form")[0];
var email = document.getElementById("mail");
// 以下是在 DOM 中访问下一个兄弟元素的技巧
// 这比较危险,很容易引起无限循环
// 在现代浏览器中,应该使用 element.nextElementSibling
var error = email;
while ((error = error.nextSibling).nodeType != 1);
// 按照 HTML5 规范
var emailRegExp =
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
// 许多旧版浏览器不支持 addEventListener 方法
// 这只是其中一种简单的处理方法
function addEvent(element, event, callback) {
var previousEventCallBack = element["on" + event];
element["on" + event] = function (e) {
var output = callback(e);
// 返回 `false` 来停止回调链,并中断事件的执行
if (output === false) return false;
if (typeof previousEventCallBack === "function") {
output = previousEventCallBack(e);
if (output === false) return false;
}
};
}
// 现在我们可以重构字段的约束校验了
// 由于不使用 CSS 伪类,我们必须明确地设置 valid 或 invalid 类到 email 字段上
addEvent(window, "load", function () {
// 在这里验证字段是否为空(请记住,该字段不是必需的)
// 如果非空,检查它的内容格式是不是合格的 e-mail 地址
var test = email.value.length === 0 || emailRegExp.test(email.value);
email.className = test ? "valid" : "invalid";
});
// 处理用户输入事件
addEvent(email, "input", function () {
var test = email.value.length === 0 || emailRegExp.test(email.value);
if (test) {
email.className = "valid";
error.innerHTML = "";
error.className = "error";
} else {
email.className = "invalid";
}
});
// 处理表单提交事件
addEvent(form, "submit", function () {
var test = email.value.length === 0 || emailRegExp.test(email.value);
if (!test) {
email.className = "invalid";
error.innerHTML = "I expect an e-mail, darling!";
error.className = "error active";
// 某些旧版浏览器不支持 event.preventDefault() 方法
return false;
} else {
email.className = "valid";
error.innerHTML = "";
error.className = "error";
}
});
该结果如下:
正如你所看到的,建立自己的校验系统并不难。困难的部分是使其足够通用,以跨平台和任何形式使用它可以创建。有许多库可用于执行表单校验; 你应该毫不犹豫地使用它们。这里有一些例子:
独立的库(原生 Javascript 实现):
Validate.js
jQuery 插件:
Validation
Valid8
远程校验
在某些情况下,执行一些远程校验可能很有用。当用户输入的数据与存储在应用程序服务器端的附加数据绑定时,这种校验是必要的。一个应用实例就是注册表单,在这里你需要一个用户名。为了避免重复,执行一个 AJAX 请求来检查用户名的可用性,要比让先用户发送数据,然后因为表单重复了返回错误信息要好得多。
执行这样的校验需要采取一些预防措施:
它要求公开 API 和一些数据;你需要确保它不是敏感数据。
网络滞后需要执行异步校验。这需要一些用户界面的工作,以确保如果校验没有适当的执行,用户不会被阻止。