实时表单验证:提升用户体验的微妙改进
核心要点:
- JavaScript 可用于实现实时表单验证,此功能可为用户提供输入有效性的即时反馈,从而提升用户体验并维护数据完整性,确保仅提交有效数据。
- HTML5 属性
pattern
和required
可用于定义表单元素的有效输入范围。如果浏览器不支持这些属性,则其值可用作 JavaScript 兼容性填充程序的基础。 -
aria-invalid
属性可用于指示字段是否无效。此属性提供辅助功能信息,并可用作 CSS 钩子以直观地指示无效字段。 - JavaScript 函数
instantValidation()
测试字段并执行实际验证,控制aria-invalid
属性以指示字段的状态。此函数可以绑定到onchange
事件以提供实时表单验证。
HTML5 引入了几个用于实现基于浏览器的表单验证的新属性。pattern
属性是一个正则表达式,用于定义文本区域元素和大多数输入类型的有效输入范围。required
属性指定字段是否必填。对于不支持这些属性的旧版浏览器,我们可以使用它们的值作为兼容性填充程序的基础。我们还可以使用它们来提供更有趣的增强功能——实时表单验证。
需要注意的是,不要过度使用验证,以免破坏正常的浏览行为并妨碍用户操作。例如,我见过一些表单,无法使用 Tab 键离开无效字段——JavaScript 被用来(更确切地说,是被滥用)强制焦点停留在字段内,直到其有效为止。这非常不利于用户体验,并且直接违反了辅助功能指南。
本文将介绍一种侵入性较小的实现方法。它甚至不是完整的客户端验证——它只是一种细微的用户体验增强,以可访问的方式实现,在我测试脚本时发现它几乎与 Firefox 当前原生实现的功能相同!
基本概念
在最新版本的 Firefox 中,如果必填字段为空或其值与模式不匹配,则该字段将显示红色边框,如下图所示:
当然,这不会立即发生。如果发生这种情况,则每个必填字段默认都会显示该边框。相反,只有在您与字段交互后才会显示这些边框,这基本上(虽然不完全)类似于 onchange
事件。
因此,我们将使用 onchange
作为触发事件。或者,我们可以使用 oninput
事件,该事件只要在字段中键入或粘贴任何值就会触发。但这真的太“即时”了,因为它很容易在快速连续键入时反复触发,从而产生闪烁效果,这会让一些用户感到厌烦或分心。而且,无论如何,oninput
不会从编程输入中触发,而 onchange
会触发,我们可能需要它来处理来自第三方插件的自动完成等操作。
定义HTML和CSS
让我们看一下我们的实现,从它所基于的 HTML 开始:
<form action="#" method="post"> <fieldset> <legend><strong>Add your comment</strong></legend> <p> <label for="author">Name <abbr title="Required">*</abbr></label> <input aria-required="true" id="author" name="author" pattern="^([- \w\d\u00c0-\u024f]+)$" required="required" size="20" spellcheck="false" title="Your name (no special characters, diacritics are okay)" type="text" value="" > </p> <p> <label for="email">Email <abbr title="Required">*</abbr></label> <input aria-required="true" id="email" name="email" pattern="^(([-\w\d]+)(\.[-\w\d]+)*@([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2})$" required="required" size="30" spellcheck="false" title="Your email address" type="email" value="" > </p> <p> <label for="website">Website</label> <input id="website" name="website" pattern="^(http[s]?:\/\/)?([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2}(\/([-~%\.\(\)\w\d]*\/*)*(#[-\w\d]+)?)?$" size="30" spellcheck="false" title="Your website address" type="url" value="" > </p> <p> <label for="text">Comment <abbr title="Required">*</abbr></label> <textarea aria-required="true" cols="40" id="text" name="text" required="required" rows="10" spellcheck="true" title="Your comment" ></textarea> </p> </fieldset> <fieldset> <input name="preview" type="submit" value="Preview"> <input name="save" type="submit" value="Submit Comment"> </fieldset> </form>
此示例是一个简单的评论表单,其中一些字段是必填的,一些字段经过验证,一些字段同时满足这两个条件。具有 required
属性的字段也具有 aria-required
属性,以便为不支持新输入类型的辅助技术提供后备语义。
ARIA 规范还定义了 aria-invalid
属性,我们将使用它来指示字段是否无效(HTML5 中没有等效属性)。aria-invalid
属性显然提供了辅助功能信息,但它也可以用作 CSS 钩子来应用红色边框:
input[aria-invalid="true"], textarea[aria-invalid="true"] { border: 1px solid #f00; box-shadow: 0 0 4px 0 #f00; }
我们可以只使用 box-shadow
而不用管边框,坦白说这样看起来会更好,但这样一来,在不支持 box-shadow
的浏览器(例如 IE8)中就没有指示了。
添加JavaScript
现在我们有了静态代码,我们可以添加脚本了。首先,我们需要一个基本的 addEvent()
函数:
function addEvent(node, type, callback) { if (node.addEventListener) { node.addEventListener(type, function(e) { callback(e, e.target); }, false); } else if (node.attachEvent) { node.attachEvent('on' + type, function(e) { callback(e, e.srcElement); }); } }
接下来,我们需要一个函数来确定是否应该验证给定字段,该函数只需测试它既未禁用也未只读,并且它具有 pattern
或 required
属性:
function shouldBeValidated(field) { return ( !(field.getAttribute("readonly") || field.readonly) && !(field.getAttribute("disabled") || field.disabled) && (field.getAttribute("pattern") || field.getAttribute("required")) ); }
前两个条件可能看起来很冗长,但它们是必要的,因为元素的 disabled
和 readonly
属性不一定反映其属性状态。例如,在 Opera 中,具有硬编码属性 readonly="readonly"
的字段仍然会为其 readonly
属性返回 undefined
(点属性只匹配通过脚本设置的状态)。
一旦我们获得了这些实用程序,我们就可以定义主验证函数,该函数测试字段,然后根据需要执行实际验证:
function instantValidation(field) { if (shouldBeValidated(field)) { var invalid = (field.getAttribute("required") && !field.value) || (field.getAttribute("pattern") && field.value && !new RegExp(field.getAttribute("pattern")).test(field.value)); if (!invalid && field.getAttribute("aria-invalid")) { field.removeAttribute("aria-invalid"); } else if (invalid && !field.getAttribute("aria-invalid")) { field.setAttribute("aria-invalid", "true"); } } }
因此,如果字段是必填的但没有值,或者它具有模式和值,但值与模式不匹配,则该字段无效。
由于模式已经定义了正则表达式的字符串形式,所以我们只需要将该字符串传递给 RegExp
构造函数,它就会创建一个我们可以针对该值进行测试的正则表达式对象。但是,我们必须预先测试该值以确保它不为空,这样正则表达式本身就不必考虑空字符串。
一旦我们确定了字段是否无效,我们就可以控制它的 aria-invalid
属性来指示该状态——将其添加到尚未具有该属性的无效字段中,或将其从具有该属性的有效字段中删除。很简单!最后,为了使这一切都能运行,我们需要将验证函数绑定到 onchange
事件。它应该像这样简单:
<form action="#" method="post"> <fieldset> <legend><strong>Add your comment</strong></legend> <p> <label for="author">Name <abbr title="Required">*</abbr></label> <input aria-required="true" id="author" name="author" pattern="^([- \w\d\u00c0-\u024f]+)$" required="required" size="20" spellcheck="false" title="Your name (no special characters, diacritics are okay)" type="text" value="" > </p> <p> <label for="email">Email <abbr title="Required">*</abbr></label> <input aria-required="true" id="email" name="email" pattern="^(([-\w\d]+)(\.[-\w\d]+)*@([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2})$" required="required" size="30" spellcheck="false" title="Your email address" type="email" value="" > </p> <p> <label for="website">Website</label> <input id="website" name="website" pattern="^(http[s]?:\/\/)?([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2}(\/([-~%\.\(\)\w\d]*\/*)*(#[-\w\d]+)?)?$" size="30" spellcheck="false" title="Your website address" type="url" value="" > </p> <p> <label for="text">Comment <abbr title="Required">*</abbr></label> <textarea aria-required="true" cols="40" id="text" name="text" required="required" rows="10" spellcheck="true" title="Your comment" ></textarea> </p> </fieldset> <fieldset> <input name="preview" type="submit" value="Preview"> <input name="save" type="submit" value="Submit Comment"> </fieldset> </form>
但是,为了使这能够工作,onchange
事件必须冒泡(使用通常称为事件委托的技术),但在 Internet Explorer 8 及更早版本中,onchange
事件不会冒泡。我们可以选择忽略这些浏览器,但我认为这将是一种遗憾,尤其是在问题如此容易解决的情况下。它只是意味着代码更复杂一些——我们必须获取输入和文本区域元素的集合,遍历它们并将 onchange
事件分别绑定到每个字段:
input[aria-invalid="true"], textarea[aria-invalid="true"] { border: 1px solid #f00; box-shadow: 0 0 4px 0 #f00; }
结论和展望
就是这样——一个简单且非侵入性的实时表单验证增强功能,提供可访问和直观的提示,以帮助用户完成表单。
这个脚本实现后,我们实际上只需要几步就能完成一个完整的兼容性填充程序。这样的脚本超出了本文的范围,但是如果您想进一步开发它,所有基本模块都在这里——测试是否应该验证字段,根据模式和/或 required
验证字段,以及绑定触发事件。
我必须承认,我不确定它是否真的值得!如果您已经有了此增强功能(在 IE7 及所有现代浏览器中都能工作),并且考虑到您别无选择,也必须实现服务器端验证,并且考虑到支持 pattern
和 required
的浏览器已经使用它们进行预提交验证——考虑到所有这些,真的还有必要添加另一个兼容性填充程序吗?
(此处可以添加关于实时验证的常见问题解答部分,内容与原文档中的FAQs部分相同)
以上是使用JavaScript即时表单验证的详细内容。更多信息请关注PHP中文网其他相关文章!

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

是的,JavaScript的引擎核心是用C语言编写的。1)C语言提供了高效性能和底层控制,适合JavaScript引擎的开发。2)以V8引擎为例,其核心用C 编写,结合了C的效率和面向对象特性。3)JavaScript引擎的工作原理包括解析、编译和执行,C语言在这些过程中发挥关键作用。

JavaScript是现代网站的核心,因为它增强了网页的交互性和动态性。1)它允许在不刷新页面的情况下改变内容,2)通过DOMAPI操作网页,3)支持复杂的交互效果如动画和拖放,4)优化性能和最佳实践提高用户体验。

C 和JavaScript通过WebAssembly实现互操作性。1)C 代码编译成WebAssembly模块,引入到JavaScript环境中,增强计算能力。2)在游戏开发中,C 处理物理引擎和图形渲染,JavaScript负责游戏逻辑和用户界面。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

禅工作室 13.0.1
功能强大的PHP集成开发环境

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

记事本++7.3.1
好用且免费的代码编辑器