1、XMLHttpRequest的基本使用
XMLHttpRequest简称xhr,是浏览器提供的JS对象,可以请求服务器上的数据资源,之前学习的到JQ中的ajax函数,就是基于xhr对象封闭出来的。
(1)使用xhr发起get请求
<script>
//1.创建xhr对象
var xhr = new XMLHttpRequest();
//2.用xhr.open()函数
xhr.open('get','http://www.liulongbin.top:3006/api/getbooks');
//3.用xhr.send()函数
xhr.send();
//4.监听xhr.onreadystatechange事件
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status ===200) {
console.log(xhr.responseText);
}
}
</script>
说明:
xhr.readyState表示当前ajax请求所处的状态,有0,1,2,3,4等4种状态,分别是创建对象、open、send、接收中、完成。
url后面可以拼接?id=1等等参数,这个参数叫‘查阅字符串“。如果要添加多个参数,可以用&并联起来。例如,?id=1,?id=1&bookname=西游记等。
$.ajax() $.get() xhr对象等发起请求,当要携带参数时,本质上是直接把参数以以查询字符串的形式,追加到URL的后面,发送给服务器。
<script>
// $.get('http://www.liulongbin.top:3006/api/getbooks',{id:1,bookname:'西游记'},function(e) {
// console.log(e);
// })
$.ajax({
method: 'get',
url: 'http://www.liulongbin.top:3006/api/getbooks',
data: {id: 2},
success: function(res) {
console.log(res);
}
})
</script>
URL中一般只当放英文的字母数字标点符号,如果出现了中文等符号,则必须进行编辑(转义)。一个汉字对应3组百分号。编码的原则,用安全的字符表示哪些不安全的字符。可以使用encodeUR() decodeURI()进行编码、解码。
<script>
var str = '白龙网';
var str2 = encodeURI(str);
console.log(str2);
var str3 = decodeURI('%E7%99%BD');
console.log(str3);
</script>
(2) 使用POST发起请求
<script>
// 1、创建xhr对象
var xhr = new XMLHttpRequest();
// 2、调用xhr.open()函数
xhr.open('post','http://www.liulongbin.top:3006/api/addbook');
// 3、设置content-type属性
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
// 4、调用xhr.send(),同时会指定发送的数据
xhr.send('bookname=水浒传&author=施耐庵&publisher=上海图书出版社');
// 5、监听xhr.onreadystatechange事件
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status ===200) {
console.log(xhr.responseText);
}
}
</script>
2、数据交换模式
数据交换的格式,就是服务器与客户端之间进行的数据传输也交换的格式。前端领域涉及的格式分别是XML,JSON。
服务器存储数据与资源,客户端接收资源与数据,此时需要数据传输与交换XML/JSON,对前端而言,JSON用的最多。
什么是XML?可扩展的标记语言,与HTML类似,但是两者之间没有任何关系。
HTML是网页内容的载体,XML用来传递数据,是数据的载体。XML的缺点,格式臃肿,和数据无关的代码多,体积大,传输效率低;解析XML麻烦。
什么是JSON,JS对象表示法,它是JS对象与数组的字符串表示,本质是字符串。作用是轻量级的文本数据交换格式,更小,更快,易于解析。成为主流的数据交换格式。
JSON包含两种结构,对象、数组。
JSON对象结构,用花括号包括起来的内容,数据结构为{"key":value},键值是用双引号包括的字符串,value是数据类型可以是数字、字符串、布尔值、null、数组、对象等六种类型。如果value是字符串,必须用双绰号包裹。value不允许出现undefined和function。
注意事项:
属性名必须使用双引号
字符患上 类型的值也必须双引号
不能写注释
最外层必须是对象或者数组格式
不能使用undefined。
JSON的作用是在计算机与网络之间传输数据,其本质是一个字符串。
JSON是JS对象的字符串表示法,它使用文本表示一个JS对象的信息,本质是一个字符串。
(1)JSON与JS对象相互转换。JSON.parse() JSON.stringify(obj)
<script>
var jsonStr = '{"siteName":"白龙网","siteTime":"从建站到SEO的在线服务平台"}';
//1.把JSON字符串转换成对象
var obj = JSON.parse(jsonStr);
console.log(obj);
//2.把对象转换成JSON字符串
var jsonstr2 = JSON.stringify(obj);
console.log(jsonstr2);
</script>
(2)服务器响应数据
通过一个案例,可以看出,从服务器拿到的响应数据是一个JSON字符串,这个字符串可以转换成数组,或者转换成对象,方便渲染到页面。
<script>
var xhr = new XMLHttpRequest();
xhr.open('get','http://www.liulongbin.top:3006/api/getbooks');
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status ===200) {
console.log(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
}
}
</script>
把数据对象转换为字符串的过程,叫序列化,例如JSON.stringify()操作,叫做JSON的序列化;反之,把字符串转换为对象的过程,叫反序列化。
3、封装ajax函数
把data对象转换为查询字符串的方式,提交给服务器
<script>
//1.封装数据处理函数
//把用户提交的对象数据转换为查询字符串:即遍历对象时,拼接对象的每个属性名和属性值并放进空数组,然后把数据中的所有元素拼接起来
function postData(data) {
var arr = [];
for (var k in data) {
var str = k + '=' + data[k];
arr.push(str);
}
return arr.join('&');
}
//2.封装自己的ajax函数
function bailong(options) {
var xhr = new XMLHttpRequest();
var qs = postData(options.data);
//判断请求类型
if(options.method.toUpperCase() === 'GET') {
//发起get请求
xhr.open(options.method,options.url + '?' + qs);
xhr.send();
} else if (options.method.toUpperCase() === 'POST') {
//发起post请求
xhr.open(options.method,options.url);
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
xhr.send(qs)
}
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status ===200) {
var results = JSON.parse(xhr.responseText);
options.success(results);
}
}
}
//3.请求数据成功
// bailong({
// method: 'GET',
// url: 'http://www.liulongbin.top:3006/api/getbooks',
// // data: {id:1},
// success: function(e) {
// console.log(e);
// }
// })
//4.提交数据成功
bailong({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/addbook',
data: {
bookname: '白龙网',
author: '京城小白龙',
publisher: '白龙出版社'
},
success: function (e) {
console.log(e);
}
})
</script>
4、XMLHttpRequest level2新特性
旧版XHR只支持文本数据的传输,无法用来读取和上传文件;传输和接收数据时,没有进度信息,只能提示有没有完成。
新版本的XHR,可设置HTTP请求的时限;可以使用formData对象管理表单数据;可以上传文件;可以获取数据传输的进度信息。
(1)xhr.timeout超时属性
设置HTTP请求时限:timeout属性设置HTTP请求时限
xhr.timeout = 3000,没有单位,默认毫秒。
与之配套的,还有一个timeout事件用来指定回调函数。
xhr.ontimeout = function() {
alert(请求超时)
}
<script>
var xhr = new XMLHttpRequest()
//1.设置超时时间
xhr.timeout = 3
//2.设置超时事件
xhr.ontimeout = function() {
console.log('超时了');
}
xhr.open('get','http://www.liulongbin.top:3006/api/getbooks')
xhr.send()
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
}
</script
(2)使用FormData对象管理表单数据
<script>
//1.创建formData实例
var fd = new FormData()
//2.调用append()函数,向实例添加数据
fd.append('uname','bailong')
fd.append('psd','123456')
//3.创建xhr对象
var xhr = new XMLHttpRequest()
//4.指定请求类型与URL
xhr.open('POST','http://www.liulongbin.top:3006/api/formdata')
//5.提交formdata对象
xhr.send(fd)
//6.监听响应数据
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
var res = JSON.parse(xhr.responseText)
console.log(res);
}
}
</script>
(3)使用FormData对象获取网页表单的值
<body>
<form id="form1">
<input type="text" name="uname" id="uname" autocomplete="off">
<input type="password" name="psd" id="psd">
<input type="submit" value="提交" id="submit">
</form>
<script>
//获取数据
var form = document.querySelector('#form1')
//监听submit按钮
form.addEventListener('submit',function(e) {
//阻止默认行为
e.preventDefault()
//把form表单数据存入fd
var fd = new FormData(form)
//创建xhr对象
var xhr = new XMLHttpRequest()
//指出请求方式、URL
xhr.open('POST','http://www.liulongbin.top:3006/api/formdata')
//发送数据
xhr.send(fd)
//监听服务器响应数据
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText))
}
}
})
</script>
</body>
(4)使用FormData对象实现上传文件
<!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-3.4.1-dist/css/bootstrap.min.css">
<script src="./jquery-3.6.0/jquery-3.6.0.min.js"></script>
</head>
<body>
<!-- 文件上传 -->
<input type="file" name="file" id="file1">
<!-- 提交 -->
<input type="submit" value=" 提交" id="filesupload">
<!-- 进度条 -->
<div class="progress" style="width: 500px;margin:15px 10px">
<div class="progress-bar progress-bar-striped active" style="width: 0%" id="percent">
0%
</div>
</div>
<!-- 显示上传的内容 -->
<br>
<img src="" alt="" id="img1" width="200">
<script>
//1.获取上传按钮元素
var filesupload = document.querySelector('#filesupload');
//2.监听上传按钮点击事件
filesupload.addEventListener('click',function() {
//3.获取用户上传文件内容
var files = document.querySelector('#file1').files;
if(files.length <= 0) {
return alert('请选择上传的文件');
}
//创建formdata
var fd = new FormData();
//追加文件
fd.append('avatar',files[0]);
//使用xhr发起上传文件的请求
var xhr = new XMLHttpRequest();
//上传进度功能实现
xhr.upload.onprogress = function(e) {
//e.lengthComputable返回返回值是布尔值,判断是否可计算
if(e.lengthComputable) {
//已上传字节数/总字节数
var percentcompute = Math.ceil( (e.loaded / e.total) * 100);
console.log(percentcompute);
$('#percent').attr('style','width:' + percentcompute + '%;').html(percentcompute + '%');
};
}
//监听上传完成后事件,改变成绿色
xhr.upload.onload = function() {
$('#percent').removeClass().addClass('progress-bar progress-bar-success')
}
xhr.open('post','http://www.liulongbin.top:3006/api/upload/avatar');
xhr.send(fd);
// 监听服务器响应数据
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
console.log(data);
if(data.status === 200) {
//上传成功
document.querySelector('#img1').src = 'http://www.liulongbin.top:3006' + data.url;
} else {
//上传失败
console.log('上传失败' + data.message);
}
}
}
})
</script>
</body>
</html>
(5)使用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-3.4.1-dist/css/bootstrap.min.css">
<script src="./jquery-3.6.0/jquery-3.6.0.min.js"></script>
</head>
<body>
<input type="file" id="file1">
<button id="btnupload">提交</button>
<br>
<img src="./loading.gif" alt="" id="loading" style="display:none">
<script>
//监听ajax发起了就显示图片
$(document).ajaxStart(function() {
$('#loading').show();
})
//监听ajax结束了就隐藏图片
$(document).ajaxStop(function() {
$('#loading').hide();
})
$(function() {
//1.判断是否上传了文件
$('#btnupload').on('click',function() {
var files = $('#file1')[0].files;
if(files.length <= 0) {
return alert('请上传文件再上传');
}
console.log('ok');
//把上传的数据放到FormData
var fd = new FormData();
fd.append('avatar',files[0]);
//发起JQuery请求,使用ajax请求
$.ajax({
method: 'post',
url: 'http://www.liulongbin.top:3006/api/upload/avatar',
data: fd,
contentType: false,//上传文件必须指定
processData: false,//上传文件必须指定
success: function(e) {
console.log(e);
}
})
})
})
</script>
</body>
</html>
5、axios库
专注于网络数据请求的库,与XMLHttpRequest而言,axios库简单易用,与jQuery相比,axios更加轻量化,只专注于网络数据请求。
(1)axios发起get请求
在写js之前,先在head区域导入axios.js库
<body>
<button id="btn">发起get请求</button>
<script>
document.querySelector('#btn').addEventListener('click',function() {
var url = 'http://www.liulongbin.top:3006/api/get';
var paramsobj = {name: 'bailong',age: 18};
//axios.get().then(function(){})
axios.get(url,{params:paramsobj}).then(function(e) {
//服务器响应的数据是e.data
console.log(e.data);
})
})
</script>
</body>
(2)axios发起post请求
同理,在使用axios.js库之前,要先引入
<body>
<button id="btn">发起post请求</button>
<script>
document.querySelector('#btn').addEventListener('click',function() {
var url = 'http://www.liulongbin.top:3006/api/post';
var paramsobj = {name: 'bailong',age: 18};
//axios.post().then(function(){})
axios.post(url,paramsobj).then(function(e) {
//服务器响应的数据是e.data
console.log(e.data);
})
})
</script>
</body>
(3)使用axios发起请求:get/post
<body>
<button id="btnget">使用axios直接发起请求GET</button>
<button id="btnpost">使用axios直接发起请求GET</button>
<script>
//axios发起get请求
document.querySelector('#btnget').addEventListener('click',function() {
var url = 'http://www.liulongbin.top:3006/api/get';
var paramsobj = {name: '白龙SEO',age: 28};
axios({
method: 'get',
url: url,
params: paramsobj
}).then(function(e) {
console.log(e.data);
})
})
//axios发起post请求
document.querySelector('#btnpost').addEventListener('click',function() {
var url = 'http://www.liulongbin.top:3006/api/post';
var data = {name: '白龙drupal',age: 66};
axios({
method: 'post',
url: url,
data: data
}).then(function(e) {
console.log(e.data);
})
})
</script>
</body>