XHR 的基本使用
什么是 XHR
xhr 是浏览器提供的 JavaScript 对象,通过它,可以请求服务器上的数据资源,之前所学的 jquery 的 ajax 函数,就是基于 xhr 对象封装出来的。
使用 xhr 发起 GET 请求
步骤 1.创建 xhr 对象 2.使用 xhr.open()函数 3.调用 xhr.send()函数 4.监听 xhr.onreadystatechange 事件。
//创建xhr对象
let xhr = new XMLHttpRequest();
//调用open函数
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks')
//调用send函数
xhr.send()
//监听事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
//获取成功
console.log(xhr.responseText);
}
}
复制代码
了解 xhr 对象的 readyState 属性
XHR 对象的 readyState 属性,用来表示当前 Ajax 请求所处的状态,每个 Ajax 请求必然处于一下状态中的一个:
使用 xhr 发起带参数的 GET 请求
使用 xhr 对象发起带参数的 get 请求时,只需在调用 xhr.open 期间,为 URL 地址指定参数即可,在地址后面写上?后面以键值对的形式写上数据,多个数据用 &连接。
//创建xhr对象
let xhr = new XMLHttpRequest();
//调用open函数
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks?id=1')
//调用send函数
xhr.send()
//监听事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
//获取成功
console.log(xhr.responseText);
}
}
复制代码
URL 编码与解码
什么是 URL 编码
URL 地址中,只允许出现英文相关的字母,标点符号,数字,因此。在 URL 地址中不允许出现中文字符。如果 URL 中需要包含中文这样的字符,则必须对中文字符进行编码(转义)。URL 编码的原则,使用安全的字符,(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。
如何对 URL 进行编码与解码
浏览器提供了 URL 编码与解码的 API,分别是:
encodeURI() 编码的函数
decodeURI()解码的函数
let str = '黑马程序员';
let str2 = encodeURI(str)
console.log(str2);
//utf-8一个汉字占三个字节 ,写六个是黑马两个字。
let str3 = decodeURI('%E9%BB%91%E9%A9%AC')
let str4 = decodeURI(str2)
console.log(str3);
console.log(str4);
复制代码
使用 xhr 发起 post 请求
步骤 1.创建 xhr 对象 2.调用 xhr.open()函数 3.设置 Content-Type 属性(固定写法)4.调用 xhr.send()函数。同时指定要发送的数据。5.监听 xhr.onreadystatechange 事件
//创建xhr对象
let xhr = new XMLHttpRequest();
//调用open()
xhr.open('post', 'http://www.liulongbin.top:3006/api/addbook');
//设置Content-Type(固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//调用send函数
xhr.send('bookname=水浒传&author=施耐庵&publisher=上海图书出版社')
//监听事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
}
复制代码
数据交换格式
什么是数据交换格式
数据交换格式,就是服务器端与客户端之间进行数据传输与交换的格式.
前端领域,经常提及的两种数据交换格式分别是 XML 和 JSON。其中 XML 用的非常少,所以,我们重点要学习的数据交换格式 JSON。
XML
什么是 XML
xml 的英文全称是 EXtensible Markup Language,即可扩展标记语言,因此,XML 和 HTML 类似,也是一种标记语言。
XML 和 HTML 的区别
xml 和 html 虽然都是标记语言,但是,他们两者之间没有任何的关系。
XML 的缺点
1.XML 格式臃肿,和数据无关的代码多,体积大,传输效率低。2.在 JavaScript 中解析 XML 比较麻烦。
JSON
什么是 JSON
概念:JSON 的英文全称是 JavaScript Object Notation,即 JavaScript 对象表示法。简单来讲,JSON 就是 JavaScript 对象和数组的字符串表示法,它使用文本表示一个 JS 对象或数组的信息,因此,JSON 的本质是字符串。
作用:JSON 是一种轻量级的文本数据交换格式,在作用上类似 XML,专门用于存储和传输数据,单是 JSON 比 XML 更小,更快,更易解析。
现状:JSON 是在 2001 年开始被推广和使用的数据格式,到现今为止,JSON 已经成为了主流的数据交换格式。
JSON 的两种结构
JSON 就是用字符串来表示 JavaScript 的对象和数组两种结构,通过这两种结构的相互嵌套,可以表示各种复杂的数据结构。
对象结构:对象结构在 JSON 中表示为{}括起来的内容,数据结构为{key:value,key:value,...}的键值对结构,其中,key 必须是使用英文的双引号包裹的字符串,value 的数据类型可以是数字,字符串,布尔值,null,数组,对象六种类型。
数组结构:数组结构在 JSON 中表示为[]括起来的内容,数据结构为['java','javascript',30,true],数组中数据的类型可以是数字,字符串,布尔值,null,数组,对象 6 种类型。
JSON 语法的注意事项
1.属性名必须使用双引号包裹。2.字符串类型的值必须使用双引号包裹 3.JSON 中不允许使用单引号表示字符串 4.JSON 中不能写注释 5.JSON 的最外层必须是对象或数组格式。6.不能使用 undefined 或函数作为 JSON 的值
JSON 的作用:在计算机与网络之间存储和传输数据。JSON 的本质:用字符串来表示 JavaScript 对象数据或数组数据。
JSON 和 JS 对象的关系
JSON 是 js 对象的字符串表示法,它使用文本表示一个 js 对象的信息,本质是一个字符串。例如:
var jsobj ={a:'hello',b:'world'}
var jsonstr = '{'a':'hello','b':'world'}'
复制代码
JSON 和 JS 对象的互转
要实现从 JSON 字符串转换为 js 对象,使用 JSON.parse()方法;
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);
var restr = JSON.parse(xhr.responseText)
console.log(restr);
}
}
复制代码
要实现从 JS 对象转换为 JSON 字符串,使用 JSON.stringify()方法:
序列化和反序列化
把数据对象转换为字符串的过程,叫做序列化,例如:调用 JSON.stringify()函数的操作,叫做 JSON 序列化。
把字符串转换为数据对象的过程,叫做反序列化,例如:调用 JSON.parse()函数的操作,叫做 JSON 的反序列化。
封装自己的 Ajax 函数
要实现的效果
定义一个名为 itheima 的 ajax 函数,导入 js 文件之后,可以进行调用文件内的相关函数。定义 options 参数选项 itheima()函数是我们自定义的 Ajax 函数,它接受一个配置对象作为参数,配置对象中可以配置如下属性:
method 请求的类型
url 请求的 URL 地址
data 请求携带的数据
success 请求成功之后的回调函数
处理 data 参数
需要把 data 对象,转化成查询字符串的格式,从而提交给服务器,因此提前定义 resolveData 函数如下:
function resolveData(data) {
var arr = [];
for (const k in data) {
//这里说一下对象的调用方法,对象调用可以使用【】和点,这里的对象调用需要用【】的,k是字符串,点后面不能是字符串,所以不能直接data.k,
//我们可以先进行字符串链接data.k再使用eval方法进行解析,就可以使用点调用了
// var str = k + '=' + eval("data." + k);
var str = k + '=' + data[k];
arr.push(str);
}
return arr.join('&')
}
var str = resolveData({ name: 'xiaoxie', age: 20 });
console.log(str);
复制代码
定义 itheima 函数
在 itheima()函数中,需要创建 xhr 对象,并监听 onreadystatechange 事件。
function itheima(options) {
let xhr = new XMLHttpRequest();
let qs = resolveData(options.data)
--------判断类型 发起请求 代码--------------
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
let result = JSON.parse(xhr.responseText)
options.success(result)
}
}
}
复制代码
判断请求的类型
不同的请求类型,对应的 xhr 对象的不同操作,因此需要对请求类型进行 if...else..的判断。
if (options.method.toUpperCase() === 'GET') {
xhr.open('get', options.URL + '?' + qs)
xhr.send();
} else if (options.method.toUpperCase() === 'POST') {
xhr.open('post', options.URL)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send(qs);
}
复制代码
xhr level2 的新特性
旧版 xhr 的缺点
只支持文本数据的传输,无法用来读取和上传文件。
传送和接受数据时,没有进度信息,只能提示有没有完成。
xhr levle2 的新特性
可以设置 http 请求的时限。
可以使用 formdata 对象管理表单数据
可以上传文件
可以获得数据传输的进度信息。
设置 http 请求时限。
有时,Ajax 操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久,新版本的 xhr 对象,增加了 timeout 属性,可以设置 http 请求的时限:
上面的语句,将最长等待时间设为 3000 毫秒,过了这个时限,就自动停止 http 请求。与之配套的还有一个 timeout 事件,用来指定回调函数。
xhr.ontimeout = function(event){
alert('请求超时')
}
复制代码
let xhr = new XMLHttpRequest();
xhr.timeout = 30;
xhr.ontimeout = function () {
console.log(请求超时);
}
xhr.open('get', 'http://liulongbin.top:3006/api/getbooks')
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
}
复制代码
FormData 对象管理表单数据
Ajax 操作往往用来提交表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单操作。
let fd = new FormData();
fd.append('uname', 'xiaoxie')
fd.append('pwd', 123456)
let xhr = new XMLHttpRequest();
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));
}
}
复制代码
FormData 对象也可以用来获取网页表单的值,不用通过 serialize()方法转换,可以获取值后可以直接使用,不用通过示例代码如下:
var form = document.querySelector('#form1')
form.addEventListener('submit', function (e) {
e.preventDefault();
//创建对象,获取数据。
let fd = new FormData(form);
let xhr = new XMLHttpRequest();
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));
}
}
})
复制代码
上传文件
新版 xhr 对象,不仅可以发送文本信息,还可以上传文件。
定义 ui 结构
验证是否选择了文件
向 FormData 中追加文件
使用 xhr 发起上传文件的请求
监听 onreadystatechange 事件定义 UI 结构
<!-- 文件选择框 -->
<input type="file" id="file1">
<!-- 上传文件的按钮 -->
<button id="btnUpload"></button>
<br>
<img src="" alt="" id="img" width="800">
复制代码
验证是否选择了文件
//获取文件上传按钮
let btn = document.getElementsByTagName('button')[0];
//为按钮绑定单击事件处理函数
btn.addEventListener('click', function () {
//获取用户选择的文件鼠标
let files = document.querySelector('#file1').files;
if (files.length <= 0) {
return alert('请选择要上传的文件')
}
console.log('用户选择了待上传的文件');
})
复制代码
向 FormData 中追加文件
let fd = new FormData()
fd.append('avatar', files[0])
复制代码
使用 xhr 发起上传文件的请求
let xhr = new XMLHttpRequest();
xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar')
xhr.send(fd)
复制代码
监听 onreadystatechange 事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
let data = JSON.parse(xhr.responseText)
if (data.status === 200) {
//上传成功
alert('上传成功')
document.getElementById('img').src = 'http://www.liulongbin.top:3006' + data.url
} else {
console.log('图片上传失败' + data.message);
}
}
}
复制代码
显示文件上传进度
新版本的 XHR 对象中,可以通过监听 xhr.upload.onprogress 事件,来获取到文件的上传进度,语法格式如下:
//监听上传进度
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
let uploadProgroess = Math.ceil((e.loaded / e.total) * 100)
console.log(uploadProgroess);
}
}
复制代码
美化进度显示
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
//设置进度条
$('#percent').attr('style', 'width:' + uploadProgroess).html(uploadProgroess + '%')
复制代码
完整代码
<!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>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>
<body>
<!-- 文件选择框 -->
<input type="file" id="file1">
<!-- 上传文件的按钮 -->
<button id="btnUpload">上传文件</button>
<br>
<img src="" alt="" id="img" width="800">
<div class="progress" style="width: 300px;">
<div class="progress-bar progress-bar-striped active" style="width: 0%" id="percent">
0%
</div>
</div>
<script>
//获取文件上传按钮
let btn = document.getElementsByTagName('button')[0];
//为按钮绑定单击事件处理函数
btn.addEventListener('click', function () {
//获取用户选择的文件属性,是一个数组。
let files = document.querySelector('#file1').files;
if (files.length <= 0) {
return alert('请选择要上传的文件')
}
//表单中添加相应的数据
let fd = new FormData()
fd.append('tupian', files[0])
//使用xhr发起上传文件的请求
let xhr = new XMLHttpRequest();
//监听上传进度
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
let uploadProgroess = Math.ceil((e.loaded / e.total) * 100)
console.log(uploadProgroess);
//设置进度条
$('#percent').attr('style', 'width:' + uploadProgroess).html(uploadProgroess + '%')
}
}
xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar')
xhr.send(fd)
//监听onreadystatechange事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
let data = JSON.parse(xhr.responseText)
if (data.status === 200) {
//上传成功
alert('上传成功')
document.getElementById('img').src = 'http://www.liulongbin.top:3006' + data.url
} else {
console.log('图片上传失败' + data.message);
}
}
}
})
</script>
</body>
</html>
复制代码
评论