# XMLHttpRequest 的基本使用
# 什么是 XMLHttpRequest
XMLHttpRequest(简称 xhr)是浏览器提供的 Javascript 对象,通过它,可以请求服务器上的数据资源。之前所学的 jQuery 中的 Ajax 函数,就是基于 xhr 对象封装出来的。
![image-20230104105154786]()
# 使用 xhr 发起 GET 请求
# 步骤
- 创建 xhr 对象
- 调用 xhr.open () 函数
- 调用 xhr.send () 函数
- 监听 xhr.onreadystatechange 事件
# 代码实现
| |
| var xhr = new XMLHttpRequest(); |
| |
| xhr.open('GET','http://www.baozi:3306/api/getbooks'); |
| |
| xhr.send(); |
| |
| 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 请求完成,这意味着数据传输已经彻底完成或者失败 |
# 使用 xhr 发起带参数的 GET 请求
使用 xhr 对象发起带参数的 GET 请求时,只需在调用 xhr.open 期间,为 URL 地址指定参数即可:这种在 URL 后面拼接的参数,叫做查询字符串
| |
| xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=1') |
| |
# 查询字符串
# 什么是查询字符串
# 定义
查询字符串(URL 参数)是指在 URL 的末尾加上用于向服务器发送信息的字符串(变量)
# 格式
将英文的?放在 URL 的末尾,然后再加上 参数=值 ,想加上多个参数的话,使用 & 符号进行分隔。以这个形式,可以将想要发送给服务器的数据添加到 URL 中。
| |
| http://www.baozi.top:3006/api/getbooks |
| |
| http://www.baozi.top:3006/api/getbooks?id=1 |
| |
| http://www.baozi.top:3006/api/getbooks?id=1&bookname=西游记 |
# 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 编码
URL 地址中,只允许出现英文相关的字母、标点符号、数字,因此,在 URL 地址中不允许出现中文字符。
如果 URL 中需要包含中文这样的字符,则必须对中文字符进行编码(转义)。
URL 编码的原则:使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。
URL 编码原则的通俗理解:使用英文字符去表示非英文字符。
http://www.liulongbin.top:3006/api/getbooks?id=1&bookname = 西游记
// 经过 URL 编码之后,URL 地址变成了如下格式:
http://www.liulongbin.top:3006/api/getbooks?id=1&bookname = 西游记
# 如何对 URL 进行编码和解码
encodeURL()
编码函数
decodeURL()
解码的函数
# 使用 xhr 发送 POST 请求
# 步骤
- 创建 xhr 对象
- 调用 xhr.open () 函数
- 设置 Content-Type 属性
- 调用 xhr.send () 函数,同时指定要发送的数据
- 监听 xhr.onreadystatechange 事件
# 代码实现
| |
| var xhr = new XMLHttpRequest(); |
| |
| xhr.open('POST','http://www.baozi.top:3306/api/addbook'); |
| |
| xhr.setRequestHeader('Content-Type','application/x-www-form-urlencode'); |
| |
| xhr.send('bookname=baozi&author=baozi&publisher=天津出版社'); |
| |
| xhr.onreadystatechange = function() { |
| if(xhr.readyState === 4 && xhr.status === 200) { |
| console.log(xhr.responseText); |
| } |
| } |
# 数据交换格式
# 什么是数据交换格式
数据交换格式,就是服务器端与客户端之间进行数据传输与交换的格式。
前端领域,经常提及的两种数据交换格式分别是 XML 和 JSON。其中 XML 用的非常少,所以,我们重点要学习的数据交换格式就是 JSON。
![image-20230104125722804]()
# XML
# 概念
XML 的英文全称是 EXtensible Markup Language,即可扩展标记语言。因此,XML 和 HTML 类似,也是一种标记语言。
| <note> |
| <to>ls</to> |
| <from>zs</from> |
| <heading>通知</heading> |
| <body>晚上开会</body> |
| </note> |
# JSON
# 概念
JSON 的英文全称是 JavaScript Object Notation,即 “JavaScript 对象表示法”。简单来讲,JSON 就是 Javascript 对象和数组的字符串表示法,它使用文本表示一个 JS 对象或数组的信息,因此,JSON 的本质是字符串。
# 作用
JSON 是一种轻量级的文本数据交换格式,在作用上类似于 XML,专门用于存储和传输数据,但是 JSON 比 XML 更小、更快、更易解析。
# 现状
JSON 是在 2001 年开始被推广和使用的数据格式,到现今为止,JSON 已经成为了主流的数据交换格式。
# JSON 的两种结构
JSON 就是用字符串来表示 Javascript 的对象和数组。所以,JSON 中包含对象和数组两种结构,通过这两种结构的相互嵌套,可以表示各种复杂的数据结构。
# 对象结构
对象结构在 JSON 中表示为 {} 括起来的内容。数据结构为 { key: value, key: value, …} 的键值对结构。其中,key 必须是使用英文的双引号包裹的字符串,value 的数据类型可以是数字、字符串、布尔值、null、数组、对象 6 种类型。
| { |
| "name": "zs", |
| "age": 20, |
| "gender": "男", |
| "address": null, |
| "hobby": ["吃饭", "睡觉", "打豆豆"] |
| } |
# 数组结构
数组结构在 JSON 中表示为 [] 括起来的内容。数据结构为 [ "java", "javascript", 30, true …] 。数组中数据的类型可以是数字、字符串、布尔值、null、数组、对象 6 种类型。
| [ "java", "python", "php" ] |
| [ 100, 200, 300.5 ] |
| [ true, false, null ] |
| [ { "name": "zs", "age": 20}, { "name": "ls", "age": 30} ] |
| [ [ "苹果", "榴莲", "椰子" ], [ 4, 50, 5 ] ] |
# JSON 和 JS 对象的关系
JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串
| |
| var obj = {a: 'Hello', b: 'World'} |
| |
| var json = '{"a": "Hello", "b": "World"}' |
# JSON 和 JS 对象相互转换
要实现从 JSON 字符串转换为 JS 对象,使用 JSON.parse () 方法:
| var obj = JSON.parse('{"a": "Hello", "b": "World"}') |
| |
要实现从 JS 对象转换为 JSON 字符串,使用 JSON.stringify () 方法:
| var json = JSON.stringify({a: 'Hello', b: 'World'}) |
| |
# 序列化和反序列化
把数据对象转换为字符串的过程,叫做序列化,例如:调用 JSON.stringify () 函数的操作,叫做 JSON 序列化。
把字符串转换为数据对象的过程,叫做反序列化,例如:调用 JSON.parse () 函数的操作,叫做 JSON 反序列化。
# XMLHttpRequest Level2 的新特性
# 认识 XMLHttpRequest Level2 的新功能
- 可以设置 HTTP 请求的时限
- 可以使用 FormData 对象管理表单数据
- 可以上传文件
- 可以获取数据传输的进度信息
# 设置 HTTP 请求时限
有时,Ajax 操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。新版本的 XMLHttpRequest 对象,增加了 timeout 属性,可以设置 HTTP 请求的时限:
上面的语句,将最长等待时间设为 3000 毫秒。过了这个时限,就自动停止 HTTP 请求。与之配套的还有一个 timeout 事件,用来指定回调函数:
| xhr.ontimeout = function(event){ |
| alert('请求超时!') |
| } |
Ajax 操作往往用来提交表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单操作:
| |
| var fd = new FormData() |
| |
| fd.append('uname', 'zs') |
| fd.append('upwd', '123456') |
| |
| var xhr = new XMLHttpRequest() |
| |
| xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata') |
| |
| xhr.send(fd) |
FormData 对象也可以用来获取网页表单的值,示例代码如下:
| |
| var form = document.querySelector('#form1') |
| |
| form.addEventListener('submit', function(e) { |
| e.preventDefault() |
| |
| var fd = new FormData(form) |
| var xhr = new XMLHttpRequest() |
| xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata') |
| xhr.send(fd) |
| xhr.onreadystatechange = function() {} |
| }) |
# 上传文件
# 步骤
- 定义 UI 结构
- 验证是否选择了文件
- 向 FormData 中追加文件
- 使用 xhr 发起上传文件的请求
- 监听 onreadystatechange 事件
# 定义 UI 结构
| <!-- 1. 文件选择框 --> |
| <input type="file" id="file1" /> |
| <!-- 2. 上传按钮 --> |
| <button id="btnUpload">上传文件</button> |
| <br /> |
| <!-- 3. 显示上传到服务器上的图片 --> |
| <img src="" alt="" id="img" width="800" /> |
# 验证是否选择了文件
| |
| var btnUpload = document.querySelector('#btnUpload') |
| |
| btnUpload.addEventListener('click', function() { |
| |
| var files = document.querySelector('#file1').files |
| if (files.length <= 0) { |
| return alert('请选择要上传的文件!') |
| } |
| |
| }) |
| |
| var fd = new FormData() |
| |
| fd.append('avatar', files[0]) |
# 使用 xhr 发起上传文件的请求
| |
| var 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) { |
| 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) |
| } |
| } |
| } |
# 显示文件上传速度
新版本的 XMLHttpRequest 对象中,可以通过监听 xhr.upload.onprogress 事件,来获取到文件的上传进度。语法格式如下:
| |
| var xhr = new XMLHttpRequest() |
| |
| xhr.upload.onprogress = function(e) { |
| |
| if (e.lengthComputable) { |
| |
| |
| var percentComplete = Math.ceil((e.loaded / e.total) * 100) |
| } |
| } |
# jQuery 高级用法
# jQuery 实现文件上传
# 定义 UI 结构
| <!-- 导入 jQuery --> |
| <script src="./lib/jquery.js"></script> |
| <!-- 文件选择框 --> |
| <input type="file" id="file1" /> |
| <!-- 上传文件按钮 --> |
| <button id="btnUpload">上传</button> |
# 验证是否选择了文件
| $('#btnUpload').on('click', function() { |
| |
| var files = $('#file1')[0].files |
| |
| if (files.length <= 0) { |
| return alert('请选择图片后再上传!‘) |
| } |
| }) |
| |
| var fd = new FormData(); |
| fd.append('avatar',files[0]); |
# 使用 jQuery 发起上传文件的请求
| $.ajax({ |
| method: 'POST', |
| url: 'http://www.baozi.top:3006/api/upload/avatar', |
| |
| contentType: false, |
| |
| processData: false, |
| success: function(res) { |
| console.log(res); |
| } |
| }) |
# jQuery 实现 loading 效果
# ajaxStart(callback)
Ajax 请求开始时,执行 ajaxStart 函数。可以在 ajaxStart 的 callback 中显示 loading 效果,示例代码如下:
| |
| $(document).ajaxStart(function() { |
| $('#loading').show() |
| }) |
# ajaxStop(callback)
Ajax 请求结束时,执行 ajaxStop 函数。可以在 ajaxStop 的 callback 中隐藏 loading 效果,示例代码如下:
| |
| $(document).ajaxStop(function() { |
| $('#loading').hide() |
| }) |
# axios
# 什么是 axios
Axios 是专注于网络数据请求的库。
相比于原生的 XMLHttpRequest 对象,axios 简单易用。
相比于 jQuery,axios 更加轻量化,只专注于网络数据请求
# axios 发起 GET 请求
| |
| var url = 'http://www.baozi.top:3006/api/get'; |
| |
| var paramsObj = {name: 'zs',age: 20}; |
| |
| axios.get(url,{params: paramsObj}).then(function(res){ |
| |
| var result = res.data; |
| console.log(result); |
| }) |
# axios 发起 POST 请求
| |
| var url = 'http://www.baozi.top:3006/api/post'; |
| |
| var dataObj = {location: '北京',address: '顺义'}; |
| |
| axios.post(url,dataObj).then(function(res) { |
| |
| var result = res.data; |
| console.log(result); |
| }) |
# 直接使用 axios 发起请求
# GET 请求
| axios({ |
| method: 'GET', |
| url: 'http://www.baozi.top:3006/api/get', |
| params: { |
| name: 'ZS', |
| age: 20 |
| } |
| }).then(function(res) { |
| console.log(res.data); |
| }) |
# POST 请求
| axios({ |
| method: 'POST', |
| url: 'http://www.baozi.top:3006/api/post', |
| data: { |
| bookname: 'SpringBoot', |
| price: 520 |
| } |
| }).then(function(res) { |
| console.log(res.data); |
| }) |