FormData对象实例讲解
1 form标签
<form>标签用于为用户输入创建html表单,向服务器传输数据。
表单能够包含input元素,比如文本字段、复选框、单选框、提交按钮等等。表单还可以包含menus、textarea、fieldset、legend和label元素。
注释:form 元素是块级元素,其前后会产生折行。
<form id="myform" action="https://www.w3school.com.cn/example/html/form_action.">
<label>姓名:
<input name="username">
</label>
<br>
<label>性别:
<input type="radio" name="gender" value="male" checked>男
<input type="radio" name="gender" value="female">女</label>
<br>
<label>住址:
<select name="address">
<option value="beijing" selected>北京</option>
<option value="nanjing">南京</option>
<option value="tokyo">东京</option>
</select>
</label>
<button type="submit" id="submit">提交</button>
<button type="reset">重置</button>
</form>
在一个表单里面,action规定当提交表单时向何处发送表单数据。当点击form表单内,type为submit的按钮时,会将表单提交到action对应的地址,而点击type为reset的按钮时,表单会被重置
想要阻止提交或者重置行为,需要使用e.preventdefault()
注意,通过form的action发送表单时,是不受跨域的限制的,原因是:
跨域指的是“跨域资源共享(cross-origin resource sharing,cors)”。当一个资源从与改资源本身所在服务器的不同的域或不同的端口请求一个资源时,资源会发起一个跨域http请求。
表单的提交方式有两种,一种是直接指定表单的action。一种是ajax接手控制请求。
直接使用action的时候,是直接把请求交给了action里面的域,本身页面不会去管他的请求结果,后面的步骤交给了action里面的域。好比:
<from action="baidu.com">
// you form filed
</from>
上面这个表单提交后,剩余的操作就交给了action里面的域baidu.com,本页面的逻辑和这个表单没啥关系,由于不关系请求的响应,所以认为是安全的。
而使用ajax来控制form的请求的时候,页面js会需要知道请求的返回值,这个时候,浏览器发出跨域请求,需要获得授权才可以成功请求,否则是会拒绝的。
2 formdata对象
xmlhttprequest level2新提那家的接口,利用formdata对象,可以通过一些键值对来模拟一系列表单空间,可以用xmlhttprequest的send方法来提交表单。
使用formdata的最大优点是可以异步上传一个二进制文件。
3 formdata对象的api
append: 用来向formdata对象添加键值对
delete
get
getall
has
set
keys
values
foreach
- entries
formdata对象的操作方法,全部在原型中,自己本身没任何的属性及方法。
let formdata = new formdata()
formdata.append('user', 'zhang')
//获取
formdata.get('user') //zhang
// 删除
formdata.delete('user')
4 从零创建一个formdata对象
const formdata = new formdata();
formdata.append("username", "groucho");
formdata.append("accountnum", 123456); //数字123456会被立即转换成字符串 "123456"
// html 文件类型input,由用户选择
formdata.append("userfile", fileinputelement.files[0]);
// blob对象
const content = '<a id="a"><b id="b">hey!</b></a>'; // 新文件的正文...
const blob = new blob([content], { type: "text/xml"});
formdata.append("webmasterfile", blob);
const request = new xmlhttprequest();
request.open("post", "https://foo.com/submitform.php");
request.send(formdata);
注意:字段userfile和webmasterfile都包含一个文件. 字段accountnum是数字类型,它将被formdata.append()方法转换成字符串类型formdata对象的字段类型可以是blob、file, 或者string: 如果它的字段类型不是blob也不是file,则会被转换成字符串类型。
一个blob对象表示一个不可变的, 原始数据的类似文件对象。blob表示的数据不一定是一个javascript原生格式。file接口基于blob,继承 blob功能并将其扩展为支持用户上的文件。你可以通过blob()构造函数创建一个blob对象。
5 通过html表单创建formdata对象
想要构造一个包含form表单数据的formdata对象,需要在创建formdata对象时指定表单的元素。
const formdata = new formdata(someformelement);
还以最上面的表单为例,
const url = 'https://www.w3school.com.cn/example/html/form_action.asp';
const myform = document.queryselector('#myform');
const submit = document.queryselector('#submit');
submit.addeventlistener('click', function(e) {
const formdata = new formdata(myform);
const request = new xmlhttprequest();
request.open('post', url);
formdata.append('hair', 'black');
request.send(formdata);
e.preventdefault()
})
还可以在创建一个包含form表单数据的formdata对象之后和发送请求之前,附加额外的数据到formdata对象里
使用fromdata对象上传文件
还可以使用formdata上传文件。使用的时候需要在表单中添加一个文件类型的input:
<form enctype="multipart/form-data" method="post" name="fileinfo">
<label>file to stash:</label>
<input type="file" name="file" required />
</form>
然后启用下面发送请求:
const form = document.forms.nameditem("fileinfo");
form.addeventlistener('submit', function(ev) {
const odata = new formdata(form);
odata.appen('extraname', 'extravalue')
const request = new xmlhttprequest();
request.open('post', 'some.php', true);
request.onreadystatechange = function() {
if (request.status == 200 && request.readystate === 4) {
console.log('发送成功')
}
}
request.send(odata);
ev.preventdefault();
})
上面:
dom nameditem()方法集合中取回带有指定名称的节点或元素。返回具有指定id或name属性的元素或节点。如果htmlcollection 中没有这样的节点,则返回null。
如果formdata对象是通过表单创建的,则表单中指定的请求方式会被应用到方法open()中。
还可以直接向formdata对象附加file或blob类型的文件,如下所示:
data.append("myfile", myblob, "filename.txt");
1
使用append()方法时,可以通过第三个可选参数设置发送请求的头content-disposition指定文件名。如果不指定文件名(或者不支持该参数时),将使用名字“blob”。
6 使用jquery
6.1 通过jquery使用formdata对象
$.ajax({
url: 'file.php',
type: 'post',
data: formdata, // 上传formdata封装的数据
datatype: 'json',
cache: false, // 不缓存
processdata: false, // jquery不要去处理发送的数据
contenttype: false, // jquery不要去设置content-type请求头
success: function(data) { //成功回调
console.log(data);
}
});
注意:new formdata的参数是一个dom对象,而非jquery对象
6.2 serialize()方法
可以不使用formdata对象,使用jquery的serialize()方法将表单结果序列化:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>form-data</title>
<script src="../lib/jquery.min.js"></script>
</head>
<body>
<form id="form">
<label><input type="radio" name="myinput1" value="a"><span>a</span></label>
<label><input type="radio" name="myinput1" value="b"><span>b</span></label>
<label><input type="radio" name="myinput1" value="c"><span>c</span></label>
<label><span>输入你的屁话</span><input type="text" name="bullshit"></label>
</form>
<p>
<button id="btn">click</button>
<span>选择结果:</span><span id="result"></span>
</p>
<script>
$('#btn').on('click', function () {
$('#result').text($("#form").serialize())
})
</script>
</body>
</html>
这个方法只能序列化表单的数据,但是对于文件(比如上传文件)则无法实现,这时候还是要使用fromdata对象了。