目录
1 FormData类型
2 文件上传
2.1 使用POST方法,将enctype属性设为application/x-www-form-urlencoded
2.2 使用POST方法,将enctype属性设为text/plain。
2.3 使用POST方法,将enctype属性设为multipart/form-data。
2.4 使用GET方法,enctype属性将被忽略。
2.5 append()
3 表单的验证
3.1 HTML 5表单验证
3.2 checkValidity方法,setCustomValidity方法,validity对象
4 在JavaScript中访问表单或表单域
FormData类型可以用于构造表单数据。
var formData = new FormData();
formData.append('username', '张三');
formData.append('email', '[email protected]');
formData.append('birthDate', 1940);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/register");
xhr.send(formData);
上面的代码构造了一个formData
对象,然后使用send方法发送。它的效果与点击下面表单的submit按钮是一样的。
FormData也可以将现有表单构造生成。
var formElement = document.querySelector("form");
var request = new XMLHttpRequest();
request.open("POST", "submitform.php");
request.send(new FormData(formElement));
FormData对象还可以对现有表单添加数据,这为我们操作表单提供了极大的灵活性。
function sendForm(form) {
var formData = new FormData(form);
formData.append('csrf', 'e69a18d7db1286040586e6da1950128c');
var xhr = new XMLHttpRequest();
xhr.open('POST', form.action, true);
xhr.onload = function(e) {
// ...
};
xhr.send(formData);
return false;
}
var form = document.querySelector('#registration');
sendForm(form);
FormData对象也能用来模拟File控件,进行文件上传。
function uploadFiles(url, files) {
var formData = new FormData();
for (var i = 0, file; file = files[i]; ++i) {
formData.append(file.name, file); // 可加入第三个参数,表示文件名
}
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onload = function(e) { ... };
xhr.send(formData); // multipart/form-data
}
document.querySelector('input[type="file"]').addEventListener('change', function(e) {
uploadFiles('/server', this.files);
}, false);
FormData也可以加入JavaScript生成的文件。
// 添加JavaScript生成的文件
var content = 'hey!';
var blob = new Blob([content], { type: "text/xml"});
formData.append("webmasterfile", blob);
HTML网页的元素能够以四种格式,向服务器发送数据。
POST
方法,将enctype
属性设为application/x-www-form-urlencoded
这种方法是默认方法,POST发送,Encoding type为application/x-www-form-urlencoded。
Content-Type: application/x-www-form-urlencoded
foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
POST
方法,将enctype
属性设为text/plain
。
这种方法是POST发送,Encoding type为text/plain。
Content-Type: text/plain
foo=bar
baz=The first line.
The second line.
POST
方法,将enctype
属性设为multipart/form-data
。
这种方法是POST发送,Encoding type为multipart/form-data。
Content-Type: multipart/form-data; boundary=---------------------------314911788813839
-----------------------------314911788813839
Content-Disposition: form-data; name="foo"
bar
-----------------------------314911788813839
Content-Disposition: form-data; name="baz"
The first line.
The second line.
-----------------------------314911788813839--
GET
方法,enctype
属性将被忽略。
这种方法是GET请求。
?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.
某个表单有两个字段,分别是foo
和baz
,其中foo
字段的值等于bar
,baz
字段的值一个分为两行的字符串。上面四种方法,都可以将这个表单发送到服务器。
通常,我们使用file控件实现文件上传。
上面HTML代码中,file控件的multiple属性,指定可以一次选择多个文件;如果没有这个属性,则一次只能选择一个文件。
file对象的files属性,返回一个FileList对象,包含了用户选中的文件。
var fileSelect = document.getElementById('file-select');
var files = fileSelect.files;
然后,新建一个FormData对象的实例,用来模拟发送到服务器的表单数据,把选中的文件添加到这个对象上面。
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (!file.type.match('image.*')) {
continue;
}
formData.append('photos[]', file, file.name);
}
上面代码中的FormData对象的append方法,除了可以添加文件,还可以添加二进制对象(Blob)或者字符串。
// Files
formData.append(name, file, filename);
// Blobs
formData.append(name, blob, filename);
// Strings
formData.append(name, value);
append方法的第一个参数是表单的控件名,第二个参数是实际的值,第三个参数是可选的,通常是文件名。
最后,使用Ajax方法向服务器上传文件。
var xhr = new XMLHttpRequest();
xhr.open('POST', 'handler.php', true);
xhr.onload = function () {
if (xhr.status !== 200) {
alert('An error occurred!');
}
};
xhr.send(formData);
目前,各大浏览器(包括IE 10)都支持Ajax上传文件。
除了使用FormData接口上传,也可以直接使用File API上传。
var file = document.getElementById('test-input').files[0];
var xhr = new XMLHttpRequest();
xhr.open('POST', 'myserver/uploads');
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);
可以看到,上面这种写法比FormData的写法,要简单很多。
所谓“表单验证”,指的是检查用户提供的数据是否符合要求,比如Email地址的格式。HTML 5原生支持表单验证,不需要JavaScript。
上面代码指定该input输入框只能填入日期,否则浏览器会报错。
但有时,原生的表单验证不完全符合需要,而且出错信息无法指定样式。这时,可能需要使用表单对象的noValidate属性,将原生的表单验证关闭。
var form = document.getElementById("myform");
form.noValidate = true;
form.onsubmit = validateForm;
上面代码先关闭原生的表单验证,然后指定submit事件时,让JavaScript接管表单验证。
此外,还可以只针对单个的input输入框,关闭表单验证。
form.field.willValidate = false;
每个input输入框都有willValidate属性,表示是否开启表单验证。对于那些不支持的浏览器(比如IE8),该属性等于undefined。
麻烦的地方在于,即使willValidate属性为true,也不足以表示浏览器支持所有种类的表单验证。比如,Firefox 29不支持date类型的输入框,会自动将其改为text类型,而此时它的willValidate属性为true。为了解决这个问题,必须确认input输入框的类型(type)未被浏览器改变。
if (field.nodeName === "INPUT" && field.type !== field.getAttribute("type")) {
// 浏览器不支持该种表单验证,需自行部署JavaScript验证
}
checkValidity方法表示执行原生的表单验证,如果验证通过返回true。如果验证失败,则会触发一个invalid事件。使用该方法以后,会设置validity对象的值。
每一个表单元素都有一个validity对象,它有以下属性。
setCustomValidity方法用于自定义错误信息,该提示信息也反映在该输入框的validationMessage属性中。如果将setCustomValidity设为空字符串,则意味该项目验证通过。
例如:
访问表单:可以使用window.document.forms[0]或window.document.forms['form1'],或者使用window.document.form1来访问表单
访问表单域:可以使用window.document.form1.text1访问值