前言
在 HTML 中应用 <form>
表单元素在 JavaScript 中对应的是 HTMLFormElement
类型,而 HTMLFormElement
继承了 HTMLElement
接口:
interface HTMLFormElement extends HTMLElement {...}
因而,HTMLFormElement
除了与 HTMLElement
有一样的属性和办法外,还有本人独有的属性和办法:
acceptCharset
:服务器能够接管的字符集,等价于 HTML 的 accept-charset 属性。action
:申请的 URL,等价于 HTML 的action
属性。elements
:表单中所有控件的HTMLCollection
。enctype
:申请的编码类型,等价于 HTML 的 enctype 属性。length
:表单中控件的数量。method
:HTTP 申请的办法类型,通常是get
或post
,等价于 HTML 的method
属性。name
:表单的名字,等价于 HTML 的name
属性。target
:用于发送申请和接管响应的窗口的名字,等价于 HTML 的target
属性。reset()
:把表单字段重置为各自的默认值,如果没有默认值,则为空。submit()
:提交表单。
如果想要获取 <form>
表单元素的援用,须要应用 DOM
选择器进行查找,如 getElementById/getElementsByName/getElementsByClassName/getElementsByTagName/querySelector/querySelectorAll
这些办法,上面应用 getElementById()
办法获取表单,只有给表单设置一个 id
属性即可:
let form = document.getElementById("form-id");
Document
中的 <form>
是document.forms
的成员,因而能够通过索引或表单的 name
来拜访特定的表单。如下所示:
// 文档中第一个元素
let firstForm = document.forms[0];
// 获得名字为 "form-name" 的表单
let formName = document.forms["form-name"];
留神:表单能够同时领有 id
和name
,且两者能够不雷同。
提交表单
个别状况下,<form>
表单元素是通过客户端用户点击的形式发送表单数据。而定义提交按钮次要有:
- 定义应用
type=“submit”
属性值的<input>
元素,如<input type="submit" value="提交">
。 - 定义应用
type="submit"
属性值的<button>
元素,如<button type="submit"> 提交 </button>
。 - 定义应用
type="image"
属性值的<input>
元素,如<input type="image" src="submit.gif">
。
这种形式提交表单会在申请之前触发 submit
事件。这就提供了一个验证表单数据的机会,能够依据验证后果来决定表单是否要提交。如下所示:
let form = document.getElementById("form-id");
form.addEventListener("submit", (event) => {
// 验证表单
if (...) {
// 验证失败后,就要阻止表单提交
event.preventDefault();
return;
}
// 这里用于验证胜利后将表单提交
});
调用 preventDefault()
办法能够阻止表单提交。通常,在表单数据有效以及不应该发送到服务器能够这样解决。
也能够调用submit()
办法提交表单,表单中不存在提交按钮也不影响提交。如下所示:
let form = document.querySelector("#form-id");
// 提交表单
form.submit();
通过 submit()
办法提交的表单,submit
事件不会触发。因而在调用这个办法前要先做数据验证。
表单提交的最大一个问题是可能会提交两次。如果提交表单后没有反馈,那么没有急躁的用户可能会屡次点击提交按钮。因而,解决这种办法次要有两种:表单提交后禁用按钮,或者通过 onsubmit
事件勾销之后的表单提交。
重置表单
个别用户填写完表单信息后,想要从新填写时,能够应用重置按钮来重置表单。而定义重置按钮次要有:
- 定义应用
type="reset"
属性值的<input>
元素,如<input type="reset" value="重置">
。 - 定义应用
type="reset"
属性值的<button>
元素,如<button type="reset"> 重置 </button>
重置胜利后,表单字段的值会重置为默认值;如果没有默认值,则会为空。
重置按钮能够触发 reset
事件。这个事件为勾销重置提供了机会。如下所示:
let form = document.getElementById("form-id");
form.addEventListener("reset", (event) => {event.preventDefault();
});
重置按钮也能够调用 reset()
办法实现重置操作:
let form = document.getElementById("form-id");
// 重置表单
form.reset();
但 reset()
办法会触发 reset
事件。
留神:表单设计中通常不提倡重置表单。
表单字段
表单元素能够像页面中的其它元素一样应用原生 DOM
办法来拜访。此外,调用 elements
属性为表单的有序列表,蕴含表单中所有标签元素的援用,包含 <input>
、<textarea>
、<button>
、<select>
和<fieldset>
元素,并依照在 HTML 中呈现的秩序保留,通过索引和 name
属性进行拜访。如下所示:
let form = document.getElementById("form-id");
// 获得表单中的第一个字段
let field1 = form.elements[0];
// 获得表单中名为 "textbox-name" 的字段
let field2 = form.elements["textbox-name"];
// 获得字段的数量
let fieldCount = form.elements.length;
如果多个表单控件应用同一个 name
值,比方 <input>
元素设置 type="radio"
属性为单选,就会返回蕴含所有同名元素的 HTMLCollection
。如下所示:
<form method="post" id="form-id">
<ul>
<li><input type="radio" name="sex" value="男"> 男 </li>
<li><input type="radio" name="sex" value="女"> 女 </li>
<li><input type="radio" name="sex" value="未知"> 未知 </li>
</ul>
</form>
因而,拜访 elements["sex"]
返回的 NodeList
就蕴含着 3 个元素;而应用索引拜访时,就会返回以后地位的元素。如下所示:
let form = document.getElementById("form-id");
let sexes = form.elements["sex"];
console.log(sexes.length); // 3
let index_one = sexes[1];
let form_one = form.elements[1];
console.log(index_one === form_one); // true
公共属性
除了 <fieldset>
元素以外,所有表单字段都有一组同样的属性。因为 <input>
类型能够示意多种表单字段,因而某些属性只实用于特定类型的字段。除此之外的属性能够在任何表单字段上应用。以下列出了这些表单字段的公共属性和办法。
disabled
:布尔值,示意表单字段是否禁用。form
:指针,指向表单字段所属的表单。这个属性是只读的。name
:字符串,这个字段的名字。readOnly
:布尔值,示意这个字段是否只读。tabIndex
:数值,示意这个字段在按 Tab 键时的切换程序。type
:字符串,示意字段类型,如 ”checkbox”、”radio” 等。value
:要提交给服务器的字段值。对文件输出字段来说,这个属性是只读的,仅蕴含计算机上某个文件的门路。
JavaScript 能够动静批改任何属性,当然,form
属性除外。如下所示:
let form = document.getElementById("form-id");
let field = form.elements[0];
// 批改字段的值
field.value = "批改后的值";
// 查看字段所属的表单
console.log(field.form === form); // true
// 给字段设置焦点
field.focus();
// 禁用字段
field.disabled = true;
// 扭转字段的类型(不举荐,但对 <input> 来说是可能的)field.type = "checkbox";
动静批改表单字段属性的能力为批改表单提供了不便。如当点击两次提交按钮时,会在第一次提交后,通过监听 submit
事件来实现禁用提交按钮。如下所示:
// 防止屡次提交表单的代码
let form = document.getElementById("form-id");
form.addEventListener("submit", (event) => {
let target = event.target;
// 获得提交按钮
let btn = target.elements["submit-btn"];
// 禁用提交按钮
btn.disabled = true;
});
以上代码,通过监听 submit
事件,并在函数中获取按钮并设置disabled=true
,来达到提交按钮禁用。留神:这个性能不能通过间接给提交按钮增加 onclick
事件进行实现,起因是不同浏览器触发事件的机会不一样。有些浏览器会在触发表单的 submit
事件前先触发 onclick
事件,有些浏览器会后触发 onclick
事件。对于先触发 onclick
事件的浏览器,这个按钮会在表单提交前被禁用,这意味着表单不会被提交。因而,最好应用表单的 submit
事件进行禁用提交按钮。但这种形式不适用于没有提交按钮的表单提交,因为,只有提交按钮能力触发 submit
事件。
type
属性能够用于除 <fieldset>
之外的任何表单字段。对于 <input>
元素,这个值等于 HTML 的 type
属性值。对于其余元素,这个 type
属性的值依照下表设置。
形容 | 示例 HTML | 类型的值 |
---|---|---|
单选列表 | <select>...</select> |
“select-one” |
多项列表 | <select multiple>...</select> |
“select-multiple” |
自定义按钮 | <button>...</button> |
“submit” |
自定义非提交按钮 | <button type="button">...</button> |
“button” |
自定义重置按钮 | <button type="reset">...</button> |
“reset” |
自定义提交按钮 | <button type="submit">...</button> |
“submit” |
对于 <input>
和<button>
元素,能够动静批改其 type
属性。但 <select>
元素的 type
属性是只读的。
公共办法
每个表单字段都有两个公共办法:
focus()
:把浏览器焦点设置到表单字段,该字段会变成流动字段并能够响应键盘事件。blur()
:从元素上移出焦点,焦点不会转移到任何特定元素,仅仅是从调用这个办法的元素上移除。
给一个 focus()
办法的例子:
window.addEventListener("load", (event) => {document.forms[0].elements[0].focus();});
上述情况就是在页面加载后,把焦点定位到表单中的第一个字段。留神:如果表单中第一个字段是 type="hidden"
属性的 <input>
元素,或者该字段被 CSS 属性 display
或 visibility
暗藏,以上代码就会出错。
在 HTML5 中,表单字段减少了 autofocus
属性,反对的浏览器会主动为带有该属性的元素设置焦点,毋庸应用 JavaScript。如下所示:
<input type="text" autofocus>
为了让之前的代码在应用 autofocus
时也能失常工作,必须先检测元素上是否设置了该属性。如果设置了 autofocus
,就不再调用 focus()
:
window.addEventListener("load", (event) => {let element = document.forms[0].elements[0];
if (element.autofocus !== true) {element.focus();
}
});
留神:默认状况下只能给表单元素设置焦点。不过,通过将 tabIndex
属性设置为–1
再调用focus()
,也能够给任意元素设置焦点。
再给一个 blur()
的例子:
document.forms[0].elements[0].blur();
在浏览器反对 readOnly
属性之前,Web 开发者通常会应用这个办法创立只读字段。当初很少有须要调用 blur()
的了。
公共事件
除了鼠标、键盘、变动和 HTML 事件外,所有字段还反对以下 3 个事件:
blur
:字段失去焦点时,会触发该事件。change
:<input>
和<textarea>
元素的value
发生变化且失去焦点时触发,或者在<select>
元素中选中项发生变化时触发。focus
:在字段取得焦点时触发。
blur
和 focus
事件是用户手动扭转焦点或调用 blur/focus
办法时触发。change
事件是因控件不同而扭转触发机会。
<input>
和<textarea>
:change
事件会在字段失去焦点,同时value
自控件取得焦点后产生扭转时触发。<select>
:change
事件会在用户扭转选中项时触发,不须要控件失去焦点。
focus
和 blur
事件通常用于扭转用户界面,提供可见的提醒或额定性能;change
事件通常用于验证用户在字段中输出的内容。比方,有的文本框可能只限于接管数值,focus
事件用来扭转控件的背景色彩以便更分明地表明以后字段取得了焦点,blur
事件用于去掉这个背景色彩,change
事件用于在用户输出了非数值时把背景色彩改为红色。如下所示:
let textbox = document.forms[0].elements[0];
textbox.addEventListener("focus", (event) => {
let target = event.target;
if (target.style.backgroundColor != "red") {target.style.backgroundColor = "yellow";}
});
textbox.addEventListener("blur", (event) => {
let target = event.target;
target.style.backgroundColor = /[^\d]/.test(target.value) ? "red" : "";
});
textbox.addEventListener("change", (event) => {
let target = event.target;
target.style.backgroundColor = /[^\d]/.test(target.value) ? "red" : "";
});
上述代码中,onfocus
事件会把文本框的背景改为黄色,表明是以后流动字段。onblur
和 onchange
事件会在发现非数值字符时把背景改为红色。为测试非数值字符,这里应用了简略的正则表达式来检测文本框的value
。这个性能必须同时在 onblur
和 onchange
事件上实现,确保无论文本框是否扭转都能执行验证。
留神:blur
和 change
事件的关系并没有明确定义。在某些浏览器中,blur
事件会先于 change
事件触发;在其它浏览器中,触发程序会相同。因而不能依赖这两个事件触发的程序,必须辨别时要多加留神。
总结
HTML 和 ECMAScript 都更新了好几个版本,然而表单简直素来没有扭转。然而,通过 JavaScript 能够减少现有表单字段以提供新性能或加强易用性。也因而,表单字段也裸露了属性、办法和事件供 JavaScript 调用应用。
更多内容请关注公众号「海人为记」