十、表单操作
编写表单的三步骤:构建表单,让用户提供信息;提交表单,将浏览器的数据按照一定的规则组织起来发送给服务器端进行处理,提供接收数据的接口地址、编码方式、处理数据的存储等信息;配置表单,将表单数据提交的信息配置到表单。
1、表单元素
(1)form
有多种方式可以取得form元素的引用。document.forms可以取得页面所有表单,通过数值索引或name值取得特定表单。
var pizzaForm=document.forms.pizza;
var myForm=document.forms["form2"];
属性和方法 |
描述 |
|
name |
表单名称 |
扫描二维码关注公众号,回复:
3432483 查看本文章
|
autocomplete |
浏览器是否自动完成表单 |
|
elements |
表单中所有控件的集合 |
|
length |
表单中控件的数量 |
|
reset() |
将所有表单域重置为默认值 |
|
acceptCharset |
被提交表单中使用的字符集 |
表单提交相关 |
enctype/encoding |
被提交数据的编码 |
|
action |
提交表单的地址 |
|
method |
提交表单时所用的HTTP方法 |
|
target |
action属性中地址的目标 |
|
noValidate |
浏览器不验证表单 |
|
submit() |
提交表单 |
autocomplete:on聚焦时显示之前输入值作候选,候选值根据输入筛选;off不出现候选,有时还会出现提示,与浏览器设置有关。
elements:元素列表,包括该表单子孙表单控件(除图片按钮<input type=”image”>),归属于该表单的表单控件(除图片按钮),如<label><input name=”d” form=”f”></label>。动态节点集合。
reset():重置表单,form, input, keygen, output, select, textarea,触发表单reset事件,阻止该事件的默认行为可取消重置,元素重置时不再触发元素上的change和input事件。如删除文件不可设置value值为空,fileForm.reset();。
(2)表单控件
testForm.elements[0]或testForm.elements[‘a’]或testForm[0]或testForm[‘a’]
其中form[name],返回id或name为指定名称的表单控件(除图片按钮),如果结果为空,则返回id为指定名称的img元素;如果有多个同名元素,则返回这些元素的动态节点集合;一旦用指定名称取过该元素,则不管该元素的id或name如何变化,只要节点还在页面上均可使用原名称获取该元素。但elements是动态节点集合,节点名称变化则不能使用原名获取。
表单控件共有属性。其中,修改form属性调整元素归属表单。
label.setAttribute('form','newFormId');
属性 |
描述 |
name |
控件名称(表单提交时名称,或elements索引) |
value |
控件提交给服务器的值,只读 |
type |
控件类型 |
form |
指向控件所属表单的指针,关联归属表单,只读 |
(3)label
htmlFor:关联表单控件激活行为,关联后点击label行为与表单控件行为保持一致。可关联元素button, input(除hidden外), keygen, meter, output, progress, select, textarea。
<!--图片按钮选择文件-->
<form class="f-hidden">
<input id="file" name="image" type="file"/> <!--0x0尺寸不可见-->
</form>
<label for="file" class="m-upload">选择文件</label> <!--上传按钮效果-->
control:指定for后自动生成该属性,指向关联的表单控件节点。如果制定了for属性,则为该属性对应id的可关联元素;如果没有指定for属性,则为第一个子孙可关联元素。
(4)input
type:控件外观、数据类型。不同type对应的属性有差异。
练习:本地图片预览,点击“添加”按钮,打开本地文件,选择多个图片文件,预览图片缩略图。
accept:支持音频audio/*、视频video/*、图片image/*、不带“;”的MIME type、以“.”开始的文件后缀名,多个类型用逗号分隔。
<input type="file" accept="image/*" multiple />
file.addEventListener('change',function(event){ //当选择的文件发送变化时
var files=Array.prototype.slice.call(event.target.files,0); //把选中的所有文件罗列
files.forEach(function(item){
file2dataurl(item,function(url){ //对每个文件取dataurl信息
var image=new Image();
image.src=url;
parent.appendChild(image);
});
});
});
(5)select
|
属性和方法 |
描述 |
select. |
multiple |
控制选择器多选 |
options |
选择器下面所有选项的集合,动态的节点集合 |
|
selectedOptions |
选择器下面所有选中选项的集合,动态的节点集合 |
|
selectedIndex |
第一个选中的选项的索引值,没有元素选中返回-1 |
|
add(element[,before]) |
在指定的位置之前添加选项,没参照则在最后 |
|
remove([index]) |
删除某个选项 |
|
optgroup. |
disabled |
当前分组中所有选项都是不可选的 |
label |
对分组的说明 |
|
option |
disabled |
该选项不可选 |
label |
说明 |
|
text |
显示在页面上让用户看到的文字 |
|
index |
当前选项的索引值 |
|
selected |
该选项是否被选中 |
|
defaultSelected |
默认情况下该选项是否被选中 |
创建选项new Option([text[,value[,defaultSelected[,selected]]]])。
//<option value="1.2">1.2 节点操作</option>
//方法1
new Option('1.2 节点操作','1.2');
//方法2
var option= document.createElement('option');
option.value='1.2';
option.textContent='1.2 节点操作';
添加选项。
var option=new Option('1.0 概述','1.0');
opt11.insertAdjacentElement(option,'beforeBegin'); //方法1
select.add(option,opt11); //方法2
删除选项。
opt12.parentNode.removeChild(opt12);
select.remove(2); //传option索引值
练习:级联下拉选择器,后面选择器可选值根据前面值变化。
<form name="course">
<select name="chapter">
<option>请选择章目录</option>
</select>
<select name="section">
<option>请选择节目录</option>
</select>
</form>
//数据定义
var chapters=[
{text:'1.DOM基础',value:'1'},
{text:'2.事件模型',value:'2'}
];
var sections={
1:[
{text:'1.1 文档树',value:'1.1'},
{text:'1.2 节点操作',value:'1.2'},
{text:'1.3 元素遍历',value:'1.3'},
{text:'1.4 样式操作',value:'1.4'},
{text:'1.5 属性操作',value:'1.5'},
{text:'1.6 表单操作',value:'1.6'}
],
2:[
{text:'2.1 事件类型',value:'2.1'},
{text:'2.2 事件模型',value:'2.2'},
{text:'2.3 事件应用',value:'2.3'}
]
};
//用选中的数据列表填充选择器
function fillSelect(select,list){
//倒序遍历,把原有选项删掉,否则索引值可能发生变化
for(var i=select.length-1;i>0;i--){
select.remove(i);
}
//根据数据列表把每一项数据添加到选择器
list.forEach(function(data){
var option=new Option(data.text,data.value);
select.add(option);
});
}
var course=document.forms.course;
fillSelect(course.chapter,chapters);
//切换章目录
course.chapter.addEventListener('change',function(event){
var value=event.target.value,
list=sections[value]||[];
fillSelect(course.section,list);
});
(6)textarea
属性和方法 |
描述 |
select() |
全选当前输入内容 |
selectionStart |
选中内容的起始位置,未选择返回光标所在位置 |
selectionEnd |
选中内容的结束位置,未选择返回光标所在位置 |
selectionDirection |
选择方向,forward、backward、null控制shift+方向键的行为 |
setSelectionRange(start,end[,direction]) |
用程序选中某些内容 |
setRangeText(replacement[,start,end[,mode]]) |
设置某个范围的内容 |
练习:@输入提示,下拉列表
textarea.addEventListener('input',function(event){
var target=event.target,
cursor=target.selectionStart;//根据起始、结束位置判断是否是光标?
if(target.value.charAt(cursor-1)==='@'){
doShowAtList(function(name){
var end=cursor+name.length;
target.setRangeText(name,cursor,end,'end');
//'end'把光标放在插入内容之后
});
}
});
其它表单元素:fieldset, button, keygen, output, progress, meter。
2、表单验证
可验证元素:button, input, select, textarea。以下情况在表单提交时不做验证:input type{hidden, reset, button};button type{reset, button};input\textarea readonly;可验证元素作为datalist的子孙节点;disabled。
属性和方法 |
描述 |
willValidate |
标明这个元素在表单提交时是否验证 |
checkValidity() |
元素通过验证则返回true,否则触发invalid事件 |
validity |
存储验证结果 |
validationMessage |
显示验证的异常信息 |
setCustomValidity(message) |
传入自定义的消息设置异常情况下显示的信息 |
validity错误信息如下。
名称 |
描述 |
valueMissing |
设置了required没有value |
typeMismatch |
value与type不符,如email, url |
patternMismatch |
value与pattern不匹配 |
tooLong |
value长度超过maxlength指定的长度 |
tooShort |
value长度小于minlength指定的长度 |
rangeUnderflow |
value值小于min指定的值 |
rangeOverflow |
value值大于max指定的值 |
stepMismatch |
value值不符合step指定的值 |
badInput |
输入不完整 |
customError |
使用setCustomValidity设置了自定义错误的信息 |
valid |
符合验证条件,上述所有条件符合,返回true |
自定义异常。
input.addEventListener('invalid',function(event){
var target=event.target;
if(target.validity.valueMissing){
target.setCustomValidity('请输入姓名!');
}
});
禁止验证,在form元素上添加novalidate属性,禁止表单提交时对所有可验证元素进行验证。
3、表单提交
隐式提交,如聚焦在输入框时按回车键提交表单。满足以下任一条件:表单有非禁用的提交按钮;没有提交按钮时,不超过一个类型为text, search, url, email, password, date, time, number的input元素。
提交过程,根据表单enctype指定的值构建要提交的数据结构,使用method指定的方式发送数据到action指定的目标。
(1)构建提交数据
从可提交元素中提取数据组装成指定的数据结构的过程,可提交元素button, input, keygen, object, select, textarea。
编码方式默认为application/x-www-form-urlencoded,数据格式的组织形式是用&分隔的键值对,适合计算机处理;multipart/form-data规范IFC2388中定义的字节流的形式发送到服务器中,适合文件上传;text/plain回车换行符分隔的键值对给人阅读。提交时Content-Type值为对应的编码方式名称。
特殊案例,name=”isindex”&&type=”text”,作为表单的第一个提交元素,编码方式为application/x-www-form-urlencoded,提交时只发送value值,不包含name。
name=”_charset_”&&type=”hidden”,没有设置value值,提交时value自动用当前提交的字符集填充,如UTF-8。
(2)表单提交
除了用提交按钮提交表单外,也可以调用form的submit()方法提交表单。无论如何提交表单,都会触发onsubmit事件,进行提交之前的数据验证,如果验证未通过,可以通过阻止事件的默认行为取消表单提交。
form.addEventListener('submit',function(event){
var notValid=false;
var elements=event.target.elements;
//TODO处理自定义的验证规则
if(notValid){
event.preventDefault();
}
});
(3)无刷新表单提交
常用Ajax实现,用iframe作中间代理,结合target属性也可以完成。
<iframe name="targetFrame" class="f-hidden"></iframe>
<form action="./api" method="post" target="targetFrame"></form>
表单提交到服务器,服务器返回结果到iframe,然后把结果提交到页面,完成了当前页面不刷新,又把表单提交到服务器拿到了返回的结果。
4、表单应用
登录接口:请求地址/api/login;请求参数telephone手机号码,password密码,MD5加密;返回结果code请求状态,200表示成功,result请求结果数据。