我们先来了解一下相对于旧版本更新了那些特性或功能,再对功能特性进行学习:
我们的老版本只支持文本数据的传送,无法用来读取和上传文件 ;传送和接受数据时,没有进度信息,只能提示有没有完成 ;受到同源限制的影响,只能向同一域名的服务器请求数据,针对同源限制,没有解决方案
相比于老版本,我们的新版本可以设置HTTP请求的时限 ;可以使用FormData对象管理表单数据; 可以上传文件 ;可以请求不同域名下的数据(跨域请求) 可以获取服务器端的二进制数据 可以获得数据传输的进度信息
本章不涉及跨域请求,跨域请求另起章节阐述
目录
五.在jQuery中我们该如何上传文件?jQuery中又有那些有用的事件?
一.设置HTTP请求时限
有时Ajax的操作很耗时,而且没有办法预知要花多长时间,假如网速很慢的话,用户需要等很久,可以说是非常的不“银性”,我们新版本XMLHttpRequest对象增加了timeout属性,可以设置HTTP的请求时限
xhr.timeout = 3000;
//3000毫秒(3秒)后没有请求成功就停止请求
不仅是timeout属性,还有配套timeout事件,好像越来越有全家桶那味儿了,timeout事件用来指定回调函数,代码示例解读:
xhr.ontimeout = function(e){
alert("请求超时,请检查网络设置");
}
我们在实际应用中来看一下请求时限该怎么使用:
var xhr = new XMLHttpRequest();
//在我们new完一个XMLHttpRequest时,设置一个请求时限
xhr.timeout = 3000;
xhr.ontimeout = function(e){
alert("请求超时了,请检查您的网络设置");
}
xhr.open("GET","http://www.XXXXXXXXXXXXXX");
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.responseText);
}
}
二.FormData对象管理表单数据
我们所学习的Ajax经常用来提交表单的数据,为了方便表单的处理,HTML5新增了FormData对象来模拟表单的操作,获取网页表单的值,并提交到服务器
我们来完成这样一个获取表单的流程:
1.new一个FormData对象
var fd = new FormData();
2.添加表单项
fd.append("username", "giao哥");
fd.append("age", 20);
3.提交到服务器
xhr.send(fd);
4.完整实现FormData提交数据
var fd = new FormData();
fd.append("username", "giao哥");
fd.append("age", 20);
var xhr = new XMLHttpRequest();
xhr.open("POST","http://XXXXXXXXXXXXXXXXXXX");
//xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//使用FormData构造函数,浏览器识别并添加请求头
xhr.send(fd);
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
console.log(JSON.parse(xhr.responseText));
}
}
5.FormData直接获取表单内的value值
var form = document.querySelector('form');
form.addEventListener("submit",function(even){
//监听表单元素submit事件
even.preventDefault();
//阻止表单默认提交行为
var fd = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.open("POST","http://XXXXXXXXXXXXXXXXXXX");
xhr.send(fd);
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
console.log(JSON.parse(xhr.responseText));
}
}
})
三.上传文件
老版本的XMLHttpRequest对象,只能从服务器取回文本数据、,新版本则可以取回二进制数据
例子:假如我们现在想上传一张照片到服务器,然后通过服务器的响应,再将图片渲染到我们的网页中
思路:先判断用户是否上传了照片,没有上传我们提示用户应该先上传照片,不对服务器发起请求;如果用户上传了照片,我们将数据提交到服务器,等待服务器响应之后渲染到页面中(判断用户是否上传了文件,可以使用表单属性 files 的长度来判断用户是否上传了文件,如果长度小于等于0,那么就判断用户并没有输入数据,大于0则将数据给到FormData对象,然后传给xhr对象的send()来进行POST提交请求,如果请求上传成功,那我们就可以把HTML页面中提前设置好的img的src属性改为API地址头+data.url(服务器返回的图片url地址),这样我们就可以将图片渲染到HTML页面中了,我们利用代码实现一下:
先初始化HTML页面:
<input type="file" id="inp">
<button id="btn">提交</button>
<img src="" id="img">
JS操作:
var inp = document.querySelector('#inp');
var btn = document.querySelector('#btn');
var img = document.querySelector("#img");
//当我们想去执行提交事件时,判断用户是否上传了文件
btn.addEventListener('click',function(){
if(inp.files.length <= 0){
return alert("请您上传文件之后再执行提交操作");
}else{
var fd = new FormData();
//判断到用户上传了文件,我们传给formdata表单对象
fd.append("img",inp.files[0]);
//成功之后,我们再将数据提交到xhr对象
var xhr = new XMLHttpRequest();
xhr.open("POST","http://XXXXXXXXXXX");
xhr.send(fd);
xhr.onreadystatechange = function(){
//返回状态码请求成功
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
var data = JSON.parse(xhr.responseText);
// console.log(data);
if(xhr.status === 200){
img.src = "http://API响应头" + data.url;
}else{
alert("上传失败,请检查您的网络设置或向我们反馈");
}
}
}
}
}
})
这样我们就成功的将图片上传到了服务器并让服务器将图片渲染到了HTML页面中
四.显示文件上传进度
新版本的XMLHttpRequest对象,传递数据的时候,有一个progress事件,通过监听xhr.upload.onprogress事件来返回进度信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file" id="inp">
<button id="btn">提交</button><br>
<div></div><br>
<img src="" id="img">
</body>
<script>
var inp = document.querySelector('#inp');
var btn = document.querySelector('#btn');
var img = document.querySelector("#img");
//当我们想去执行提交事件时,判断用户是否上传了文件
btn.addEventListener('click',function(){
if(inp.files.length <= 0){
return alert("请您上传文件之后再执行提交操作");
}else{
var fd = new FormData();
//判断到用户上传了文件,我们传给formdata表单对象
fd.append("img",inp.files[0]);
//成功之后,我们再将数据提交到xhr对象
var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e){
if(e.lengthComputable){
//.lengthComputable是一个布尔值,表示当前上传的数据是否有可计算的长度
var percentComplete = Math.ceil((e.loaded / e.total)*100) + "%";
//e.loaded:已传输字节
//e.total:总共需传输字节
document.querySelector('div').innerHTML = percentComplete;
xhr.upload.onload = function(){
//上传完毕之后
document.querySelector('div').style.color = 'green';
document.querySelector('div').style.fontWeight = 'bold';
}
}
}
xhr.open("POST","http://XXXXXXXXXXXXXXXXXXXXXXXXXX");
xhr.send(fd);
xhr.onreadystatechange = function(){
//返回状态码请求成功
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
var data = JSON.parse(xhr.responseText);
// console.log(data);
if(xhr.status === 200){
img.src = "API响应头" + data.url;
}else{
alert("上传失败,请检查您的网络设置或向我们反馈");
}
}
}
}
}
})
</script>
</html>
我们在xhr对象创建完成之后开始监听请求信息,完成显示进度的功能
五.在jQuery中我们该如何上传文件?jQuery中又有那些有用的事件?
在JQuery中实现文件的上传请求时,除了较为方便,还需要再Ajax函数中添加俩个必要值:
contentType:false;
processDate:false;
在 ajax 中 contentType 设置为 false 是为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件
在使用jQuery的$.ajax()方法的时候参数processData默认值为true,会将发送的数据序列化以适应默认的内容类型application/x-www-form-urlencoded
如果想发送不想转换的的信息的时候需要手动将其设置为false
我们这里做了解就好,我们在使用jQuery上传文件请求时只要将这俩个值添加上就好
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./bootstrap.min.css">
<script src="./jQuery-min.js"></script>
</head>
<body>
<input type="file" id="userfile">
<button id="btnfile">点击上传</button>
<br>
<img src="" id="image">
</body>
<script>
$(function(){
$("#btnfile").on("click",function(){
var haveor = $("#userfile")[0].files;
if(haveor.length <= 0){
return alert("请选择文件后上传");
}
var fd = new FormData();
fd.append('avatar',haveor[0]);
$.ajax({
method:"POST",
url:"http://www.XXXXXXXXXXXXX",
data:fd,
contentType:false,
processData:false,
success:function(res){
// console.log(res);
$("#image").attr("src","API响应头" + res.url);
}
})
})
})
</script>
</html>
jQuery中还可以实现loading效果
我们可以监听全局的Ajax请求,如果发起Ajax发起或者结束Ajax请求,就会触发指定事件,执行回调函数
ajaxStart(callback):当Ajax发起请求时,执行callback回调函数
ajaxStop(callback):当Ajax结束请求时,执行callback回调函数
该方法只能被附加到文档,意思除了书写代码需要注意document外,它的监听范围时是当前文档内的所有Ajax请求结束动作
$(document).ajaxStart(function(){
$("div").show();
})
//当有Ajax请求发起时,div就会显示出来