H5的FormData与ajax2对象详解
2017-01-07 01:59

  H5中不止页面功能有了很强大的提升,就连交互功能也有和很大改善,FormData,ajax2对象可以让我们异步提交数据,包括文件对象。这是一个很不错的东西,免去了我们之前的iframe方式上传文件,提交表单的繁琐。这两个对象目前浏览器对一些常用的方法支持性尚可,可以在IE10+的浏览器中使用。甚至我们可以抛弃IE,Microsoft都放弃IE了,我们为什么还要揪着IE不放呢。

  下面我们就介绍一下这两个对象中有用的方法,以及其使用方式:

FormData对象:

   FormData对象提供一种简单的方式创建一个包含键值对的form表单结构,我们可以用XMLHttpRequest.send()方法很方便的提交用FormData创建的form表单数据。我们可以通过new 的方式创建一个FormData对象。如下:

var fm=new FormData();


FormData的方法:

FormData.append(name,value);

   添加一条数据到FormData对象中,与FormData.set()方法的区别是,如果添加的数据key值已经存在,append方法会在key值对应的values末尾添加value值,而set方法会覆盖原来的values值。

FormData.delete(name);

  从formData中删除一条key/value键值对。

FormData.entries()

 返回一个迭代器对象iterator,可以遍历formData中的所有的键值对数据。

FormData.get(name)

从formData对象中根据name返回第一条value的值。

var formData = new FormData();
formData.append('username', 'Chris');
formData.append('username', 'Bob');
formData.get('username'); 
// Returns "Chris"


FormData.getAll(name)

从formData对象中根据name返回所有的value值组成的一个Array数组

var formData = new FormData();
formData.append('username', 'Chris');
formData.append('username', 'Bob');
formData.getAll('username'); 
// Returns ["Chris", "Bob"]

FormData.has(name)

判断FormData对象中是否包含给定的name的键值。返回一个boolean值。

var formData = new FormData();
formData.has('username'); 
// Returns false
formData.append('username', 'Chris');
formData.has('username'); 
// Returns true

FormData.keys()

 返回FormData对象中所有的keys值的一个迭代器iterator。

var formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
// 遍历所有的key值。
//for of是ES6的一种新语法,跟for in的功能一样。
for (var key of formData.keys()) {
   console.log(key);
}

FormData.set(name,value)

设置formdata对象中key/value键值对,如果key已经存在,在设置value为新的value值,如果key不存在,则添加一条key/value键值对数据。

set和append方法都有第三个可选参数filename,用来添加到header中的“Content-Disposition”属性的value值发送到服务器,各个浏览器不相同。

var formData = new FormData();
formData.set('username', 'Chris');
formData.set('userpic', myFileInput.files[0], 'chris.jpg');

FormData.values()

返回一个formData对象中所有values值的一个迭代器iterator对象,可以用来遍历所有的value值。


上述方法中提到的iterator是H5的对象迭代器对象,用来迭代遍历对象内容。

var someString = "hi";
typeof someString[Symbol.iterator];         
 // "function"
var iterator = someString[Symbol.iterator]();
iterator + "";                               
// "[object String Iterator]"
 iterator.next();                             
 // { value: "h", done: false }
 iterator.next();                             
 // { value: "i", done: false }
 iterator.next();                             
 // { value: undefined, done: true }

iterator迭代其可以通过entries()方法获取。可以通过Symbol.iterator属性获取默认的迭代器,Symbol是一个常量符号对象的集合,Symbol.iterator其实就是一个常量字符串,Symbol还有一些其他的常量:比如Symbol.replace,Symbol.match等。

iterator.next()返回的done表示是否到集合的结尾,如果是true,表示已经到结尾。

Symbol,iterator的兼容性不是很好,移动端几乎不支持,电脑端目前稍微得考虑IE9+的浏览器,IE系列也全部支持,就连safari也不怎么支持。所以了解一下就性,实际项目中最好不要使用,如果非要使用,需要引入一些兼容的JS库。其实得不偿失,用我们的for循环不是美美的么,多余用迭代器何苦呢,ES添加的新功能,使得js有点失去原味的意味,不知是好是坏。新的语法太多了,这里就不展开说了,有时间单独写一篇文章介绍下。


FormData的兼容性如下图:

formdata.png

从兼容性可以看到,对于FormData对象能放心用的方法也就append方法,其实大部分场景下,我们需要的也就只有一个append方法而已。


下面我们再来看看ajax2中的介绍:

XMLHttpRequest的构造方法

    XMLHttpRequest最开始是由微软,火狐,苹果,谷歌设计实现的,现在有了标准规范。现在XMLHttpRequest可以用来传输任何数据,不止限于XML,不止支持HTTP协议,还包括file,ftp。

var myRequest=new XMLHttpRequest();


AJAX2属性:

XMLHttpRequest.onreadystatechange

当readState属性改变时调用的回调函数。

XMLHttpRequest.readyState 只读

返回一个无符号整型数据,表示request的状态。

readyState的状态值如下:

0:UNSENT-open()方法还没有调用,

1:OPENED-open()方法已经调用,

2:HEADERS_RECEIVED-send()方法已经调用,并且headers和status已经返回是有效的。

3:LOADING-正在请求中,responseText含有部分数据。

4:DONE-请求已经完成。

这里提一句,web版聊天功能,dwr等的长连接实现就是基于readyState的状态值,服务以一直返回3值,这时候responseText有数据可以处理,就能保证client和servers保持连接,及时收到另一端client发送的信息,但是这种方式需要服务器的连接数足够才可。另一种方式是使用setTimeout或者setInterval不停的请求后台来实现此类功能。

XMLHttpRequest.response 只读

返回的数据实体,根据XMLHttpRequest.responseType的设置,可以是ArrayBuffer,Blob,Document,JS对象,DOMString。

XMLHttpRequest.responseText 只读

返回一个DOMString字符串,表示请求返回的结果中的内容文本格式,如果请求没有成功或者还没有请求则为null。

XMLHttpRequest.responseType

获取或设置ajax2返回数据格式的类型,可选值为:

“”(默认DOMString文本格式),

“arraybuffer”,

“blob”,

“document”,

“json”,

“text”(跟默认值相同),

XMLHttpRequest.responseURL 只读

返回请求的路径URL地址。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/test', true);
xhr.onload = function () {
  console.log(xhr.responseURL); 
  // http://example.com/test
};
xhr.send(null);

XMLHttpRequest.responseXML 只读

返回一个document(xml)格式的数据,如果请求没有成功或者还没有发出请求,或者反回的数据不能转化成xml或者html,则返回null。


XMLHttpRequest.status 只读

返回请求状态的无符号整型标志。请求返回之前状态是0,返回后状态是200.


XMLHttpRequest.timeout

一个无符号整型,用来设置请求的超时时间,单位是毫秒。

XMLHttpRequestEventTarget.ontimeout

请求超时时的回调事件。

var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);
xhr.timeout = 2000; 

xhr.onload = function () {
  .....
 };
 
xhr.ontimeout = function (e) {
  ....
  };
xhr.send(null);


XMLHttpRequest.upload 只读

上传进度对象。用来获取上传文件的进度。

返回一个XMLHttpRequestUpload对象,代表上传的进度,此对象可以添加以下事件监听:

onloadstart:请求开始事件回调

onprogress:数据正在传输时的回调

onbort:传输中断的回调。

onerror:传输出错时的回调。

onload:传输成功时的回调。

ontimeout:传输超时时的回调。

onloadend:传输结束时的回调,无论成功与否。


上面这些事件不止upload对象有,xhr对象也有这些事件可以调用,upload表示上传文件进度,xhr上的事件可以表示是下载进度。


在upload上的onprogress方法接收的event对象有时三个参数:

event.loaded-返回上传的完成的字节数。

event.total-返回上传的总字节数

event.lengthComputable-返回boolean值,为真表示event.total不为0.

常做以下用法:

var xhr=new XMLHttpRequest();
xhr.open("post","mooshine/upload",true);
var fm=new FormData();
//从input file中获取的文件files对象,
//或者用过FileReader()从drop中的dataTransfer.files获取files对象。
fm.append("upfile",files[0]);
xhr.upload.onprogress=function(evt){
    if(evt.lengthComputable){
        var percent=evt.loaded/evt.total;
        ....
    }
};
xhr.send(fm);


在xhr上的onprogress方法接收的event对象有两个特殊参数:

event.loaded-已经上传的数据大小。

event.size-上传文件的总大小。


xhr2.withCredentials

设置是否允许跨域,默认是false,如果是CORS跨域的话,需要在发送请求前设置该属性为true。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);


xhr2的方法

xhr2.abort()

如果请求已经发出,则中断请求。


xhr2.getAllResponseHeaders()

获取所有的返回结果头信息,通过换行分割,是字符串形式的。如果服务器还没有返回,为null,如果网络发生错误,是空字符串。


xhr2.getResponseHeader(name)

返回特定名称name的header信息的值,如果服务器还没有返回,或者headers中不包含此字段,返回null

var client = new XMLHttpRequest();
client.open("GET", "mooshine.txt", true);
client.send();
client.onreadystatechange = function() {
  if(this.readyState == this.HEADERS_RECEIVED) {
    console.log(client.getResponseHeader("Content-Type"));
  }
}


xhr2.overrideMimeType()

覆盖服务器返回的MIME类型,此方法必须在send方法前调用才有作用。


xhr2.open(method,url,async)

初始化请求

method为请求的方法:true/false,

url为请求的路径,

async,是否是异步请求,默认为true(异步),false时为同步请求。


xhr2.send()

发送求情,如果是异步请求,请求发出就返回,如果是同步,服务器返回结果此方法才返回,会造成阻塞。

void send();
void send(null);
void send(ArrayBufferViewdata);
void send(Blobdata);
void send(Documentdata);
void send(DOMString?data);
void send(FormDatadata);

send方法可以发送各种数据,并且会根据数据格式做相应的序列化处理。

xhr2.setRequestHeader()

设置请求的header头信息,此方法必须在open之后,send之前调用。

XMLHttpRequest的兼容性如下图:

xhr2.png

兼容性还算不错,抛开IE,大部分功能还是支持的。

利用ajax2和FormData的一些新特性,我们可以发送文件,还可以检测发送进度。给一段例子代码:

var xhr=new XMLHttpRequest();
xhr.open("post","upload",true);
var fm=new FormData();
fm.append("upfile",files[i]);

xhr.onreadystatechange=function(){
    if(xhr.readyState==4&&xhr.status==200){
        alert("上传功能");
    }
};
//上传进度
xhr.upload.onprogress=fucntion(evt){
    if(evt.lengthComputable){
        var percent=evt.loaded/evt.total;
        //更新DOM进度条的状态
        ....
    }
};
xhr.send(fm);

对照ajax2上传文件代码还ajax2的api已经formData的api,上传文件的代码还是十分简单的。最起码比不了解ajax2之前要简单的多,那种神秘感也消失了。

天不早了,睡觉了。




原创文章,转载请注明来自:妹纸前端-www.webfront-js.com.
阅读(5892)
辛苦了,打赏喝个咖啡
微信
支付宝
妹纸前端
妹纸前端工作室 | 文章不断更新中
京ICP备16005385号-1