1. AJAX的工作原理
Ajax的工作原理相当于在用户和服务器之间加了—个中间层(AJAX引擎),使用户操作与服务器响应异步。但并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做, 只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。如图:
同时要想弄明白ajax原理必须了解XMLHTTPRequest对象
我们知道Ajax的一个最大的一个特点就是是无刷新更新页面,这一特点主要得益于XMLHTTP组件XMLHTTPRequest
对象。
2. XMLHTTPRequest对象。
- XMLHttpRequest(简称 xhr)是浏览器提供的 Javascript 对象,通过它,可以请求
服务器上的数据资源
- XMLHttpRequest对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容
XMLHTTPRequest对象使用步骤:
- 创建 xhr 对象
- 调用 xhr.open() 函数
- 调用 xhr.send() 函数
- 监听 xhr.onreadystatechange 事件
// 1. 创建 XHR 对象
var xhr = new XMLHttpRequest()
// 2. 调用 open 函数
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
// 3. 调用 send 函数
xhr.send()
// 4. 监听 onreadystatechange 事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// 获取服务器响应的数据
console.log(xhr.responseText)
}
}
注意
:xhr对象的readyState属性
XMLHttpRequest 对象的 readyState 属性,用来表示当前 Ajax 请求所处的状态
。每个 Ajax 请求必然处于以下状态中的一个
值 | 状态 | 描述 |
---|---|---|
0 | UNSENT | XMLHttpRequest 对象已被创建,但尚未调用 open方法。 |
1 | OPENED | open() 方法已经被调用。 |
2 | HEADERS_RECEIVED | send() 方法已经被调用,响应头也已经被接收。 |
3 | LOADING | 数据接收中,此时 response 属性中已经包含部分数据。 |
4 | DONE | Ajax 请求完成 ,这意味着数据传输已经彻底完成或失败 |
HTTP响应状态码的组成及分类:
HTTP 状态码由三个十进制数
字组成,第一个十进制数字定义了状态码的类型,后两个数字
用来对状态码进行细分。
HTTP 状态码共分为 5 种类型:
分类 | 分类描述 |
---|---|
1** | 信息 ,服务器收到请求,需要请求者继续执行操作(实际开发中很少遇到 1** 类型的状态码) |
2** | 成功 ,操作被成功接收并处理 |
3** | 重定向 ,需要进一步的操作以完成请求 |
4** | 客户端错误 ,请求包含语法错误或无法完成请求 |
5** | 服务器错误 ,服务器在处理请求的过程中发生了错误 |
具体状态码参考:菜鸟教程
2.1 使用xhr发GET请求
使用xhr发起带参数的GET请求
定义
:查询字符串(URL 参数)是指在 URL 的末尾加上用于向服务器发送信息的字符串(变量)。
格式
:将英文的 ? 放在URL 的末尾,然后再加上 参数=值 ,想加上多个参数的话,使用 & 符号进行分隔。以这个形式,可以将想要发送给服务器的数据添加到 URL 中。
使用 xhr 对象发起带参数的 GET 请求时,只需在调用 xhr.open 期间,为 URL 地址指定参数即可:
xhr.open(‘GET’, 'http://www.liulongbin.top:3006/api/getbooks?
id=1'
)
这种在 URL 地址后面拼接的参数,叫做查询字符串
。
GET请求带参数的本质
无论使用 $.ajax(),还是使用 $.get(),又或者直接使用 xhr 对象发起 GET 请求,当需要携带参数的时候,本质上,都是直接将参数以查询字符串的形式,追加到 URL 地址的后面,发送到服务器的。
$.get('url', {name: 'zs', age: 20}, function() {})
// 等价于
$.get('url?name=zs&age=20', function() {})
$.ajax({ method: 'GET', url: 'url', data: {name: 'zs', age: 20}, success: function() {} })
// 等价于
$.ajax({ method: 'GET', url: 'url?name=zs&age=20', success: function() {} })
如何对URL进行编码与解码
浏览器提供了 URL 编码与解码的 API,分别是:
- encodeURI() 编码的函数
- decodeURI() 解码的函数
2.2 使用xhr发起POST请求
XML对象发起post请求使用步骤:
- 创建 xhr 对象
- 调用 xhr.open() 函数
- 设置
Content-Type
属性(固定写法) - 调用 xhr.send() 函数,同时指定要发送的数据
- 监听 xhr.onreadystatechange 事件
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest()
// 2. 调用 open()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook')
// 3. 设置 Content-Type 属性(固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 4. 调用 send(),同时将数据以查询字符串的形式,提交给服务器
xhr.send('bookname=水浒传&author=施耐庵&publisher=天津图书出版社')
// 5. 监听 onreadystatechange 事件
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
3. xhr对象上传图像文件文件
新版 XMLHttpRequest 对象,不仅可以发送文本信息,还可以上传文件。
实现步骤:
- 定义 UI 结构
- 验证是否选择了文件
- 向 FormData 中追加文件
- 使用 xhr 发起上传文件的请求
- 监听 onreadystatechange 事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!-- CDN引入 -->
<link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.slim.min.js"></script>
</head>
<body>
<!-- 1. 文件选择框 -->
<input type="file" id="file1" />
<!-- 2. 上传文件的按钮 -->
<button id="btnUpload">上传文件</button>
<!-- bootstrap 中的进度条 -->
<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 />
<!-- 3. img 标签,来显示上传成功以后的图片 -->
<img src="" alt="" id="img" width="800" />
<script>
// 1. 获取到文件上传按钮
var btnUpload = document.querySelector('#btnUpload')
// 2. 为按钮绑定单击事件处理函数
btnUpload.addEventListener('click', function() {
// 3. 获取到用户选择的文件列表
var files = document.querySelector('#file1').files
if (files.length <= 0) {
return alert('请选择要上传的文件!')
}
var fd = new FormData()
// 将用户选择的文件,添加到 FormData 中
fd.append('avatar', files[0])
var xhr = new XMLHttpRequest()
// 监听文件上传的进度
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
// 计算出上传的进度
// e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
// e.loaded 已传输的字节
// e.total 需传输的总字节
var procentComplete = Math.ceil((e.loaded / e.total) * 100)
console.log(procentComplete)
// 动态设置进度条
$('#percent').attr('style', 'width: ' + procentComplete + '%;').html(procentComplete + '%')
}
}
// 文件上传成功后重新设置进度条
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)
if (data.status === 200) {
// 上传成功
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
} else {
// 上传失败
console.log('图片上传失败!' + data.message)
}
}
}
})
</script>
</body>
</html>
4. AJAX的优缺点
优点
:
- 局部刷新页面,减少用户等待时间,带来更好的用户体验
- 按需取数据,减轻服务器的负担,最大程度减少冗余请求
- 异步方式与服务器通信,不需要打断用户的操作,具有更加迅速地响应能力
缺点
- Ajax只是局部刷新,所以页面的后退按钮是没用的
- 对流媒体还有移动设备的支持不是太好
- 客户端过肥,太多客户端代码造成开发商的成本,编写复杂、容易出错,冗余代码比较多,破坏了web的原有标准
详细Ajax 的工作原理参考简书