目录
一、form简介
form标签是网页上负责数据采集的元素,称为表单。我们常见的登录页面,其主体构成就是一个form表单,它的内部通常包含若干个用于采集数据的输入框和一个提交按钮,如图(图中白色区域即为表单):
form标签从互联网诞生初期就一直存在(它的诞生早于JavaScript,因此表单可以在完全不依赖JavaScript的情况下正常使用,实际上,正是表单催生了JavaScript)。下面是一个常见的表单(省略了样式代码):
<form action="/user/userLogin.do" method="post">
<div class="form-example">
<label for="name">用户名: </label>
<input type="text" name="name" id="name" required>
</div>
<div class="form-example">
<label for="password">密码: </label>
<input type="password" name="password" id="password" required>
</div>
<div class="form-example">
<input type="submit" value="提交">
</div>
</form>
输入用户名密码,点击提交即可将数据提交到地址/user/userLogin.do
。如果验证通过,页面通常会被重定向到系统首页。如果验证失败,一般会重定向到当前页面,并给出登陆失败的提示。由于需要重定向,所以通过form提交数据时,页面往往会刷新。
在前端发展历程与技术应用概述一文中我们讲到过,在互联网发展早期,网速相对较慢。网站用户提交一个表单,通常要十几甚至几十秒才能看到提交结果。假如用户漏填了表单中的某个必填项,等了几十秒后系统才给出提示,这对用户来说是不可接受的。
为了在表单提交前就对所提交的数据进行一些简单的验证(如某项是否为空,或格式是否正确),JavaScript诞生了。当时JavaScript的最主要任务就是表单验证,以减少因用户的输入失误而导致的漫长等待。
随着JavaScript的发展,它早已不再局限于进行简单的字段验证了。ajax技术允许开发者不使用action属性提交表单,而是使用JavaScript直接手动提交。ajax方式手动提交表单的好处是,提交完表单后页面不会重定向,因此网页不需要刷新。这在很多情况下可以提升用户体验。
此外,JavaScript的DOM模块提供了原生的FormData
构造函数,用于构造一个表单对象。通过FromData.prototype.append
方法可以向表单添加要提交的数据。这样,即使你的HTML中没有包含form表单,仍然可以模拟表单提交数据。这个后面会详细介绍。
二、form的全局属性
1. action
定义表单的提交地址。
当点击类型为submit
的按钮时,浏览器就会将当前表单提交到action所指定的地址。如:
<form id="form" action="/user/userLogin.do">
<input name="username">
<input type="submit" value="提交">
</form>
点击提交按钮,用户名参数就会提交到/user/userLogin.do
进行处理。
除了上面的自动提交外,还可以通过JavaScript的DOM模块直接调用表单对象的submit
方法手动提交。如:
var form = document.getElementById("form");
// 如果确定知道是页面的第几个表单,也可以这样写
// var form = document.forms[0];
form.submit(); // 提交表单
该行为与点击类型为submit
的按钮是一致的。
2. accept-charset
服务器支持的编码格式列表,允许设置多个值,标准规定这多个值必须用空格隔开(HTML4允许使用空格或逗号隔开,但HTML5规定只能使用空格)。
该属性的默认值是“UNKNOWN”,此时表单的编码格式与当前文档一致。当设置单个值时,表单将使用该格式进行编码。当设置了多个值时,浏览器将按书写顺序,以其支持的第一个编码格式对表单进行编码。如:
<form action="" accept-charset="UTF-8 GBK ISO-8859-1">
...
</form>
当浏览器支持UTF-8,就会将表单编码设置为UTF-8,否则就向后检查。一般来说,表单都会使用与当前网页相同的编码格式,因此这个属性很少使用。
3. autocomplete
自动填充表单。
浏览器具备记忆输入历史的能力。如:
将autocomplete
设置为on
,就可以开启这个功能(该属性默认就是on,因此这里可以省略)。
<form action="" autocomplete="on">
...
</form>
此时,当用户点击曾经输入过数据的输入框时,浏览器就会自动弹出历史记录,帮助用户快速填充表单。当用户输入若干个字符后,浏览器还会过滤出历史记录中符合当前输入的数据。
对于保密性较强的字段,可以将autocomplete
属性设置为off
,阻止浏览器记录历史记录。
对form标签设置autocomplete
属性会对该表单内的所有输入控件生效。如果表单内少数控件与其他控件表现不一致,可以单独为这些控件再定义autocomplete
属性。
4. enctype
定义当表单使用POST方式提交时,表单所使用的MIME(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型,是一种文档解析标准,不同的MIME类型,解析方式也不一样)类型。
早期的表单无法上传文件,此时表单的所有字段都可以以类似url查询参数的格式提交到后台,这类表单的MIME类型被定义为application/x-www-form-urlencoded
,表示要像url参数一样去解析表单数据。
而当提交的表单中包含文件字段时,就不能使用这种MIME类型了,因为文件无法像url查询参数一样处理。对于包含文件字段的表单,需要将enctype
参数设置为multipart/form-data
,表示这是一个由多部分构成的表单(文本和文件)。如:
<form action="" enctype="multipart/form-data">
<input type="file" name="file">
...
</form>
此外,HTML5还新增了一种类型:text/plain
,此时表单将作为纯文本上传。
5. method
表单的提交方式,包括post
、get
和dialog
。
post
是最常用的提交方式,对表单数据来说更安全,也是表单提交的推荐方式。
get
会使表单参数作为查询参数直接拼接到action属性值的后面,以get的方式提交数据。这样容易导致数据被窃取,因此只能用于数据没有保密要求的情况。
dialog
用于当form表单位于<dialog>
标签内,需要在提交完表单后关闭dialog时可以使用。
6. name
表单的名称。
一般用id来代替。不同于input
的name
属性,form标签的name
属性一般仅仅用于快速定位表单,因此完全可以用id代替。
需要注意的是,HTML5要求页面内所有表单的name
属性不可重复,这与id不可重复的要求是类似的。所以一旦使用了name
属性,就要注意这个问题。
7. target
指定表单提交后,由哪个页面加载后台的返回值。
我们知道,提交表单通常都会发生重定向,通过该参数,我们可以修改重定向页面的显示位置。该参数有五个值:
- _self,在当前页显示重定向页面,是该属性的默认值。此时后台返回的重定向页面会替换当前页面,即页面发生跳转。
- _blank,在新的文档窗口内加载返回值。此时浏览器会创建新的页签显示重定向页面,而保留当前网页。
- _parent,在父窗口加载返回值。如果当前表单位于iframe内,提交表单后,重定向页面会被加载到父页面。否则行为与_self一致。
- _top,在顶层窗口加载返回值。重定向的页面会被加载到最顶级的窗口,即完全替换当前页面,无论该表单被嵌套在多少层iframe内。
- iframename,在执行的iframe内加载返回值。此时重定向的页面会被加载到指定的iframe内。
三、form的输入控件
form表单的输入控件主要是input
元素,根据type
值的不同,可以输入不同类型的数据。一般格式为:
<input type="text" name="username">
name
属性是input
标签很重要的属性。提交表单时,name
就是该参数的字段名,也就是说,后台是根据name
属性来获取表单参数的。而实际提交到服务器的值保存在input
对象的value
属性中。
下面是常用的input
类型:
- button,普通按钮。 与
<button>
标签类似,一般用于执行JavaScript代码。 - checkbox,复选框。定义的是一组多选按钮。需要注意的是,同一组复选框必须使用相同的
name
,这样才会作为一个字段提交到后台。 - color(HTML5),拾色器。其实就是一个颜色输入框,与普通输入框不同的是,点击该字段会自动打开浏览器的拾色器。点击进行取色后,该颜色值就会自动填入
input
。 - date(HTML5),日期选择器。点击会弹出一个calendar控件,可以选择一个日期,精确到年/月/日。
- datetime(HTML5),带有time的日期选择器。它比date更精确,可以选择时/分/秒。
- datetime-local(HTML5),与datetime类似的日期选择器。但使用的时间格式为网站所在地区的格式,而非国际标准格式。
- month(HTML5),用来选择月份的输入框。
- week(HTML5),用来选择周的输入框。
- time(HTML5),会弹出一个time控件,来选择时/分/秒。
- email(HTML5),邮箱输入控件。用于输入邮箱地址。
- file,文件上传控件。点击即可从本地选择文件上传到服务器。为其设置
multiple
属性可以允许该控件一次上传多个文件,这些文件被保存在一个数组中,通过控件对象的files
属性可以访问。 - hidden,隐藏表单域。设置了属性
type="hidden"
的input
不会显示在页面上,但是它的值会正常提交到服务器。这类输入框常用于随表单提交一些不需要用户手动填写的数据,或者用于保存少数的全局数据。举个例子,假如我们需要采集用户的登录位置,而这个值并不需要用户输入,我们就可以调用浏览器的地理位置接口获取地理位置信息,保存在表单的隐藏字段内提交。此时用户不会感知到我们采集了位置信息(前提是用户没有禁用地理位置)。 - image,图片类型的提交按钮。功能类似于
submit
,提交按钮是一张图片时可以使用。 - number(HTML5),数字输入框。该输入框只能输入数值,包括阿拉伯数字和小数点。默认带一个上下箭头,用于对当前值加一或减一。
- password,密码输入框。该控件的内容输入时会被遮蔽起来,通常显示为圆点或星号(与浏览器实现有关)。
- radio,单选按钮。需要注意,单选按钮组的每个选项必须是相同的
name
。 - range(HTML5),带有slider滑块的数值字段(如音量调节器,滑动滑块可以改变数值)。
- reset,重置按钮。点击该按钮可以重置表单。
- search,搜索框。
- submit,提交按钮。点击类型为
submit
的按钮即可提交当前表单,提交位置为form
标签的action
属性值。 - tel(HTML5),用于输入电话号码。
- text,普通文本字段,input控件的默认类型。
- url,用于输入一个url。
除了input
标签外,form还支持诸如select
(下拉选择框)、textarea
(多行文本域)这样的输入控件,这里不再详述。
四、form的手动提交
这里所说的手动提交不是上文介绍的调用表单对象的submit
方法提交表单,而是通过ajax
的方式来提交表单。这种方式不需要后台重定向,对于不需要刷新页面的场景非常实用。
为了书写简单,我们用jQuery来实现,使用其他框架如axios也是类似的。
1. 构造表单数据对象
手动提交表单前,需要先获取表单数据。JavaScript提供了原生的表单对象构造函数:FormData
。如果是存在于当前页面的表单,可以直接用表单对象来构造表单数据对象:
var form = document.getElementById("form");
var formData = new FormData(form);
这里的formData就是我们的表单数据对象,可以直接将其提交到服务端。
如果我们只是想以表单的形式向服务器提交一组数据,而在页面上行并没有这样一个表单,也可以直接通过FormData
构造出表单数据对象,然后通过append
方法向其添加字段。如:
var formData = new FormData();
formData.append("username", "carter");
formData.append("password", "123");
此时的formData
也是一个可提交的表单数据对象,只是它不需要从现有的表单对象构造出来。
2. 提交表单
使用常见的post方式提交即可:
$.ajax({
url : "/user/userLogin.action",
type : "POST",
data : formData,
contentType: "multipart/form-data",
success : function(data) {
... // 提交成功
},
error: function (error) {
... // 提交失败
}
});
如果表单数据不包含文件,也可以将contentType
设置为application/x-www-form-urlencoded
(需要与后端一致)。
上述代码是单独提交一个文件的很常见的方式,此时我们只需要页面上提供一个file类型的input标签用于获取要上传的文件,然后将文件对象存储在formData对象内即可,不必在页面上专门为其设置一个表单。
关于FormData对象,MDN - FormData文档中有非常详细的介绍,需要了解的可以自行查阅。
总结
form表单中包含的知识点虽然算不上特别多,但几乎都是与日常开发息息相关的。要熟练掌握表单,最重要的是要熟练使用各种类型的input
,其次需要用新的HTML5标签将表单语义化,如filedset和legend。