ajax
AJAX:Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)
1. 初识 AJAX
1.1 XML 简介(已被 JSON 替代)
XML:Extensible Markup Language(可扩展标记语言)。被设计用于传输和存储数据
1.2 AJAX 优缺点
优点:
- 无需刷新页面与服务器进行通信
- 允许根据用户事件来更新部分页面内容
缺点:
- 没有浏览历史,不能回退
- 存在跨域问题(同源)
- SEO 不友好
1.3 AJAX + HTTP 协议请求报文与响应文本结构
HTTP(hypertext transport protocolo)协议(超文本传输协议),协议详细规定了浏览器和万维网服务器之间互相通信的规则
请求报文:
- 请求行:
GET/POST/...
:请求方法/s?ie=utf-8
:urlHTTP/1.1
- 请求头:
Host: atguigu.com
Cookie: name=guigu
Content-type: application/x-www-form-urlencoded
User-Agent: chrome 84
- 空行
- 请求体(
get
时为空,post
时可以为:username=admin&password=admin
)
响应报文:
- 响应行:
HTTP/1.1
200
:状态码OK
:状态字符串
- 响应头:
Content-type: text/html;charset=utf-8
Content-length: 2048
Content-encoding: gzip
- 空行
- 响应体:
<html>
<head>
</head>
<body>
<h1>响应体</h1>
</body>
</html>
2
3
4
5
6
7
2. AJAX 基础
2.1 安装 express
yarn init
:初始化项目yarn add express
:安装express
框架
xx.js:
// 1.引入 express
const express = require('express')
// 2.创建应用对象
const app = express()
// 3.创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/', (request, response) => {
// 设置响应体
response.send('hello express')
})
// 4.监听端口启动服务
app.listen(8000, () => {
console.log('服务已经启动,8000 端口监听中')
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 执行:
node xx.js
- 访问:
localhost:8000
就能访问到了
2.2 请求基本操作
点击 '点击发送请求',会打印响应行、响应头和响应体
server.js:
// 1.引入 express
const express = require('express')
// 2.创建应用对象
const app = express()
// 3.创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/server', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应体
response.send('hello ajax')
})
// 4.监听端口启动服务
app.listen(8000, () => {
console.log('服务已经启动,8000 端口监听中')
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
get.html:
<!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>AJAX</title>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px purple;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
const btn = document.querySelector('button')
const result = document.querySelector('#result')
btn.addEventListener('click', function () {
// 1.创建对象
const xhr = new XMLHttpRequest()
// 2.初始化,设置请求方法和 url
xhr.open('GET', 'http://127.0.0.1:8000/server')
// 3.发送
xhr.send()
// 4.事件绑定,处理服务端返回的结果
// readystate 是 xhr 对象中的属性,表示状态。它有 5 个值:0 1 2 3 4
// 0:未初始化;1:open 方法调用完毕;2:send 方法调用完毕;3:服务端返回部分结果;4.服务端返回全部结果
xhr.addEventListener('readystatechange', function () {
// 判断(服务端返回了所有的结果)
if (xhr.readyState === 4) {
// 判断响应的状态码:200 404 403 500
// 2xx 成功
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果 行 头 空行 体
// 1.响应行
// console.log(xhr.status) // 状态码
// console.log(xhr.statusText) // 状态字符串
// console.log(xhr.getAllResponseHeaders()) // 响应头
// console.log(xhr.response) // 响应体
// 设置 result 的文本
result.innerHTML = xhr.response
}
}
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2.3 设置请求参数
get.html:
xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300')
点击发送后打开控制台里的网络,可以在负载中看到请求参数
2.4 发送 POST 请求
server.js:设置 post
的路由规则
// 1.引入 express
const express = require('express')
// 2.创建应用对象
const app = express()
// 3.创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/server', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应体
response.send('hello ajax')
})
app.post('/server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
response.send('hello ajax post')
})
// 4.监听端口启动服务
app.listen(8000, () => {
console.log('服务已经启动,8000 端口监听中')
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
post.html:
<!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>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px purple;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
const result = document.querySelector('#result')
result.addEventListener('mouseover', function () {
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://127.0.0.1:8000/server')
xhr.send()
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response
}
}
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2.5 POST 设置请求体
xhr.send('a=100&b=200&c=300')
2.6 设置请求头信息
post.html:
xhr.open('POST', 'http://127.0.0.1:8000/server')
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 自定义请求头,必须在后端进行设置后才能得到响应,否则报错
xhr.setRequestHeader('name', 'yuanxinyue')
2
3
4
5
6
server.js:
// 可以接收任意类型的请求
app.all('/server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
// 任何类型的请求头都可以接受(自定义的也行)
response.setHeader('Access-Control-Allow-Headers', '*')
response.send('hello ajax post')
})
2
3
4
5
6
7
2.7 服务端响应 JSON 数据
JSON.html:
<!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>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px purple;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
const result = document.querySelector('#result')
window.addEventListener('keydown', function () {
const xhr = new XMLHttpRequest()
// 设置响应体数据的类型
xhr.responseType = 'json'
xhr.open('GET', 'http://127.0.0.1:8000/json-server')
xhr.send()
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 手动对数据转化
// let data = JSON.parse(xhr.response)
// console.log(data) // {name: 'yuanxinyuehahaha'}
// result.innerHTML = data.name
// 自动转化
console.log(xhr.response) // {name: 'yuanxinyuehahaha'}
result.innerHTML = xhr.response.name
}
}
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
server.js:
// 可以接收任意类型的请求
app.all('/json-server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
// 任何类型的请求头都可以接受(自定义的也行)
response.setHeader('Access-Control-Allow-Headers', '*')
// 响应一个数据
const data = {
name: 'yuanxinyuehahaha'
}
// 对对象进行字符串转换
let str = JSON.stringify(data)
// send 只支持字符串和 buffer 类型(专门存储二进制数据的)
response.send(str)
})
2
3
4
5
6
7
8
9
10
11
12
13
14
2.8 nodemon 自动重启工具
前面的操作中,只要修改了后端代码,就需要重新运行一遍:
node server.js
,特别麻烦
- 安装:
yarn add nodemon
- 终端输入:
npx nodemon server.js
,就能开启服务了
2.9 请求超时与网络异常处理
net.html:
const xhr = new XMLHttpRequest()
// 超时设置 2s 设置
xhr.timeout = 2000
// 超时回调
xhr.addEventListener('timeout', function () {
alert('网络异常,请稍后重试')
})
// 网络异常回调
xhr.addEventListener('error', function () {
alert('你的网络似乎除了一些问题')
})
xhr.open('GET', 'http://127.0.0.1:8000/delay')
2
3
4
5
6
7
8
9
10
11
12
server.js:
// 延时响应
app.all('/delay', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
setTimeout(() => {
response.send('延时响应')
}, 3000);
})
2
3
4
5
6
7
2.10 取消请求
cancel.html:
// 获取元素对象
const btns = document.querySelectorAll('button')
let x = null
btns[0].addEventListener('click', function () {
x = new XMLHttpRequest()
x.open('GET', 'http://127.0.0.1:8000/delay')
x.send()
})
// abort
btns[1].addEventListener('click', function () {
x.abort()
})
2
3
4
5
6
7
8
9
10
11
12
13
14
server.js:
app.all('/delay', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
setTimeout(() => {
response.send('延时响应')
}, 3000);
})
2
3
4
5
6
2.11 请求重复发送问题
如果有相同的请求,则取消当前发送的重复请求
repeat.html:
<body>
<button>点击发送</button>
<script>
// 获取元素对象
const btns = document.querySelectorAll('button')
let x = null
// 表示变量
let isSending = false // 是否正在发送 ajax 请求
btns[0].addEventListener('click', function () {
// 判断表示变量
if (isSending) x.abort() // 如果正在发送,则取消该请求,创建一个新的请求
x = new XMLHttpRequest()
isSending = true
x.open('GET', 'http://127.0.0.1:8000/delay')
x.send()
x.addEventListener('readystatechange', function () {
if (x.readyState === 4) {
// 修改标识变量
isSending = false
}
})
})
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server.js:
app.all('/delay', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
setTimeout(() => {
response.send('延时响应')
}, 3000);
})
2
3
4
5
6
3. jQuery 的 ajax
3.1 $.get、$.post
jquery.html:
<h2>jQuery发送Ajax请求</h2>
<button>get</button>
<button>post</button>
<button>通用性方法ajax</button>
<script>
$('button').eq(0).on('click', function () {
// 参数:请求行的 url、请求参数、响应体
$.get('http://127.0.0.1:8000/jquery-server', {a: 100, b: 200}, (data) => {
console.log(data) // {"name":"yuanke"}
})
})
$('button').eq(1).on('click', function () {
// 参数:请求行的 url、请求参数、响应体、响应体类型
$.post('http://127.0.0.1:8000/jquery-server', {a: 100, b: 200}, (data) => {
console.log(data) // {name: 'yuanke'}
}, 'json')
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server.js:
// jquery 服务
app.all('/jquery-server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
const data = {name: 'yuanke'}
response.send(JSON.stringify(data))
})
2
3
4
5
6
3.2 jQuery 通用方法发送 AJAX 请求
jquery.html:
$('button').eq(2).on('click', function () {
$.ajax({
// url
url: 'http://127.0.0.1:8000/jquery-server',
// 请求参数 / 请求体,get / post 用这个
data: {a: 100, b: 200},
// 请求类型
type: 'GET',
// 响应体结果
dataType: 'json',
// 回调获得响应体
success: data => {
console.log(data) // {name: 'yuanke'}
},
timeout: 2000,
// 失败的回调
error: () => {
console.log('出错了!')
},
// 自定义请求头
headers: {
c: 300,
d: 400
}
})
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server.js:
// jquery 服务
app.all('/jquery-server', (request, response) => {
response.setHeader('Access-Control-Allow-Headers', '*')
response.setHeader('Access-Control-Allow-Origin', '*')
const data = {name: 'yuanke'}
response.send(JSON.stringify(data))
})
2
3
4
5
6
7
4. axios
4.1 基本形式
<!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>axios</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<button>GET</button>
<button>POST</button>
<button>AJAX</button>
<script>
const btns = document.querySelectorAll('button')
btns[0].addEventListener('click', function () {
// GET 请求
axios.get('http://127.0.0.1:8000/axios-server', {
// url 参数(get 里的请求参数)
params: {
id: 100,
vip: 7
},
headers: {
name: 'yuanxin',
age: 20
}
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
4.2 axios.get / axios.post
axios/axios: Promise based HTTP client for the browser and node.js (github.com)open in new window
<!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>axios</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<button>GET</button>
<button>POST</button>
<button>AJAX</button>
<script>
const btns = document.querySelectorAll('button')
// 配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000'
btns[0].addEventListener('click', function () {
// GET 请求
axios.get('/axios-server', {
// url 参数(get 里的请求参数和 post 里的请求体)
params: {
id: 100,
vip: 7
},
headers: {
name: 'yuanxin',
age: 20
}
}).then(value => {
console.log(value)
})
})
btns[1].addEventListener('click', function () {
// POST 请求
axios.post('/axios-server', {
// post 的话,第二个参数是一个请求体
username: 'admin',
password: 'admin'
}, {
// 请求参数
params: {
id: 200,
vip: 9
},
// 请求头
headers: {
height: 100,
weight: 180
}
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
4.3 axios 通用方法
btns[2].addEventListener('click', function () {
axios({
// 请求方法
method: 'POST',
// url
url: '/axios-server',
// 请求参数
params: {
vip: 10,
level: 30
},
// 请求头
headers: {
a: 100,
b: 200
},
// 请求体
data: {
username: 'admin',
password: 'admin'
}
}).then(response => {
console.log(response)
// 响应状态码
console.log(response.status)
// 响应状态字符串
console.log(response.statusText)
// 响应头
console.log(response.headers)
// 响应体
console.log(response.data)
})
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
5.fetch
fetch.html:
<!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>
<button>AJAX请求</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
fetch('http://127.0.0.1:8000/fetch-server', {
// 请求方法
method: 'POST',
// 请求头
headers: {
'name': 'yuanke'
},
// 请求体
body: 'username=admin&password=admin'
}).then(response => {
// return response.text()
return response.json()
}).then(response => {
console.log(response)
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
server.js:
// fetch 服务
app.all('/fetch-server', (request, response) => {
response.setHeader('Access-Control-Allow-Headers', '*')
response.setHeader('Access-Control-Allow-Origin', '*')
const data = {name: 'yuanke'}
response.send(JSON.stringify(data))
})
2
3
4
5
6
7
6.其他
6.1 同源策略
网页的 url 和目标资源的 utl 的协议、域名、端口号必须完全相同。违背同源策略就是跨域
同源策略小案例
只要输入 127.0.0.1:9000/home 就能进入该案例
index.html:
<!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>
<h1>haha</h1>
<button>点击获取用户数据</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
const x = new XMLHttpRequest()
// 这里因为是满足同源策略的,所以 url 可以简写
x.open('GET', '/data')
// 发送
x.send()
x.addEventListener('readystatechange', function () {
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
console.log(x.response)
}
}
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
server.js:
const express = require('express')
const app = express()
app.get('/home', (request, response) => {
// 响应一个页面
response.sendFile(__dirname + '/index.html')
})
app.get('/data', (request, response) => {
// 发送响应体
response.send('用户数据')
})
app.listen(9000, () => {
console.log('服务已经启动')
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
6.2 解决跨域 - JSONP
JSONP 是一个非官方的跨域解决方案,纯粹凭借程序员聪明才智开发出来的,只支持 get 请求
工作方法:
网页一些标签天生具有跨域能力,例如 img、link、iframe、script
,JSONP 就是利用 script
标签的跨域能力来发送请求的
使用方法:
- 客户端使用
script
标签引入服务端 url - 服务端需要返回 js 代码(
response.end('console.log("hhh")')
) - 如果服务端返回一个函数名(带参数),则客户端必须要声明该函数
示例代码:
index.html:
<!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>axios</title>
<style>
#result {
width: 300px;
height: 100px;
border: solid 1px #78a;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
// 处理函数
function handle(data) {
// 获取 result 元素
const result = document.querySelector('#result')
result.innerHTML = data.name
}
</script>
<script src="http://127.0.0.1:8000/jsonp-server"></script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server.js:
// jsonp 服务
app.all('/jsonp-server', (request, response) => {
// response.send('console.log("hello jsonp")')
const data = {
name: '尚硅谷aa'
}
// 将数据转化成字符串
let str = JSON.stringify(data)
// 返回结果
response.end(`handle(${str})`)
})
2
3
4
5
6
7
8
9
10
11
6.3 原生 jsonp 实践
文本框输入内容,点击文本框外的区域进行确认。这时文本框边框变红,且响应体的 msg 显示在下面
index.html:
<body>
用户名:<input type="text" id="username" />
<p></p>
<script>
const input = document.querySelector('input')
const p = document.querySelector('p')
// 声明 handle 函数
function handle(data) {
input.style.border = 'solid 10px #f00'
p.innerHTML = data.msg
}
input.addEventListener('blur', function () {
let username = this.value
// 向服务端发送请求,检测用户名是否存在
// 1.创建一个 script 标签
const script = document.createElement('script')
// 2.设置标签的 src 属性
script.src = 'http://127.0.0.1:8000/check-username'
// 3.将 script 插入到文档中
document.body.appendChild(script)
})
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
server.js:
// 用户名检测是否存在
app.all('/check-username', (request, response) => {
const data = {
exist: 1,
msg: '用户名已经存在'
}
// 将数据转化成字符串
let str = JSON.stringify(data)
// 返回结果
response.end(`handle(${str})`)
})
2
3
4
5
6
7
8
9
10
11
6.4 CORS 跨域
Cross-Origin Resource Sharing:跨域资源共享
response.setHeader('Access-Control-Allow-Origin', '*') // 允许任何 url 跨域
response.setHeader('Access-Control-Allow-Headers', '*') // 允许自定义请求头
response.setHeader('Access-Control-Allow-Method', '*') // 允许任意请求方法
2
3
7.axios 深入了解
7.1 json-server 的安装
Install JSON Server:
yarn global add json-server
Create a db.json file with some data:
{ "posts": [ { "id": 1, "title": "json-server", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } }
1
2
3
4
5
6
7
8
9Start JSON Server:
json-server --watch db.json
7.2 json-server 基本使用
<!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.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<h1>基本使用</h1>
<button>发送GET请求</button>
<button>发送POST请求</button>
<button>发送PUT请求</button>
<button>发送DELETE请求</button>
<script>
const btns = document.querySelectorAll('button')
btns[0].addEventListener('click', function () {
// 发送 axios 请求
axios({
// 请求类型
method: 'GET',
url: 'http://localhost:3000/posts/2'
}).then(response => {
console.log(response)
})
})
// 添加一篇新的文章,id 自动 +1
btns[1].addEventListener('click', function () {
axios({
method: 'POST',
// 向 db.json 的 posts数组 中添加请求体的内容
url: 'http://localhost:3000/posts',
// 设置请求体
data: {
title: '今天天气不错,还挺风和日丽的',
author: '张三'
}
}).then(response => {
console.log(response)
})
})
// 更新数据,url 后的 3 为要更新的内容
btns[2].addEventListener('click', function () {
axios({
method: 'PUT',
// 向 db.json 的 posts 数组中的第三个内容改成 data 里的数据
url: 'http://localhost:3000/posts/3',
// 设置请求体
data: {
title: '今天天气不错,还挺风和日丽的',
author: '李四'
}
}).then(response => {
console.log(response)
})
})
// 删除数据
btns[3].addEventListener('click', function () {
axios({
method: 'DELETE',
// 向 db.json 的 posts数组 中添加请求体的内容
url: 'http://localhost:3000/posts/3'
}).then(response => {
console.log(response)
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
7.3 axios 的基本使用
<!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.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<h1>基本使用</h1>
<button>发送GET请求</button>
<button>发送POST请求</button>
<button>发送PUT请求</button>
<button>发送DELETE请求</button>
<script>
const btns = document.querySelectorAll('button')
// 发送 GET 请求
btns[0].addEventListener('click', function () {
axios.request({
method: 'GET',
url: 'http://localhost:3000/comments'
}).then(response => {
console.log(response)
})
})
// 发送 POST 请求
btns[1].addEventListener('click', function () {
axios.post('http://localhost:3000/comments', {
'body': '喜大普奔',
'postId': 2
}).then(response => {
console.log(response)
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
7.4 axios 请求响应结果的结构
config
:包括请求行、请求头、请求体等data
:响应体的结果,自动解析为了对象headers
:响应头request
:原生的 ajax 请求对象,例如就包括status
响应状态码和status
响应字符串等
7.5 axios 配置对象
axios/axios: Promise based HTTP client for the browser and node.js (github.com)open in new window
url、method、baseURL、params、headers
:url、请求方法、基础url、请求参数、请求头transformRequest: (data, headers) => {}
:对请求体和请求头在发送前进行处理transformResponse: data => {}
:对响应体在then
之前进行处理paramsSerializer: params => {}
:对请求参数进行序列化,转换成字符串
axios({
url: '/post',
params: {
a: 100,
b: 200
}
// 一般情况下,自动转化为 --> /post?a=100&b=200
// 如果变成 --> /post/a/100/b/200
// 或者 --> /post/a.100/b.200
})
2
3
4
5
6
7
8
9
10
data
:请求体设置。两种形式:- 对象形式:自动将其转成 json 字符串形式传递
- URL 参数形式:直接传递
timeout
:超时时间withCredentials
:跨域请求时对 cookie 的携带做一个设置,false 为不携带,true 为在跨域请求时把 cookie 携带过去adapter: config => {}
:对请求的适配器做设置,有两种:一种是在客户端发送 ajax 的,一种是在 nodejs 环境发送 http 请求的auth
:对请求的基础验证(较少使用)responseType
:默认为json
,即服务器默认返回响应体格式为 json 格式responseEncoding
:响应结果的编码,默认为 utf-8xsrfCookieName、xsrfHeaderName
:对 cookie 的名字和 header 的名字做唯一标识,为了防止跨站攻击onUploadProgress: progressEvent => {}
:上传的回调onDownloadProgress: progressEvent => {}
:下载的回调maxContentLength
:http 响应体的最大内容,单位为字节maxBodyLength
:请求体的最大内容,单位为字节validateStatus: status => {}
:对响应结果的成功做设置(什么情况下认定成功)maxRedirects
:最大跳转次数socketPath
:设定 socket 文件的位置,向 docker 的守护进程做数据转发httpAgent
:少用httpsAgent
:少用proxy
:代理,特别常用cancelToken
:对 ajax 做一个取消的设置decompress
:压缩,nodejs 才能用
7.6 默认配置 config
形式:
axios.defaults.xxx = 'xxx'
示例代码:
<body>
<h1>基本使用</h1>
<button>发送GET请求</button>
<button>发送POST请求</button>
<button>发送PUT请求</button>
<button>发送DELETE请求</button>
<script>
const btns = document.querySelectorAll('button')
// 默认配置
axios.defaults.method = 'GET' // 设置默认请求类型为 GET
axios.defaults.baseURL = 'http://localhost:3000' // 设置基础 URL
axios.defaults.params = { id: 100 }
axios.defaults.timeout = 3000
btns[0].addEventListener('click', function () {
axios({
url: '/posts'
}).then(response => {
console.log(response)
})
})
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
7.7 创建实例对象发送请求
上面的默认配置在从多个服务器发送数据时就不好使了,这时候需要一个通用的配置:实例对象
示例代码:
<script>
const btns = document.querySelectorAll('button')
const duanzi = axios.create({
baseURL: 'https://api.apiopen.top',
timeout: 2000
})
// 这里 duanzi 与 axios 对象的功能几近是一样的
duanzi({
url: '/getJoke'
}).then(response => {
console.log(response)
})
duanzi.get('/getJoke').then(response => {
console.log(response.data)
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
7.8 拦截器
- 拦截器执行顺序是:请求拦截器越后越先拦截,响应拦截器越先越先执行
- 请求拦截器可以拦截配置对象,并对配置对象进行操作(例如:
config.params = { a: 200 }
),然后返回 config - 响应拦截器可以拦截 response,并对 response 进行操作(例如:
return response.data
)
<!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.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
// 执行顺序 2 1 1 2
// 设置请求拦截器 config 配置对象
axios.interceptors.request.use(config => {
console.log('请求拦截器 成功 - 1号')
// 修改 config 里的参数
config.params = { a: 100 }
return config
// throw '参数除了问题'
}, error => {
console.log('请求拦截器 失败 - 1号')
return Promise.reject(error)
})
axios.interceptors.request.use(config => {
console.log('请求拦截器 成功 - 2号')
// 修改 config 中参数
config.timeout = 2000
return config
// throw '参数除了问题'
}, error => {
console.log('请求拦截器 失败 - 2号')
return Promise.reject(error)
})
// 设置响应拦截器
axios.interceptors.response.use(response => {
console.log('响应拦截器 成功 - 1号')
return response.data
}, error => {
console.log('响应拦截器 失败 - 1号')
return Promise.reject(error)
})
axios.interceptors.response.use(response => {
console.log('响应拦截器 成功 - 2号')
console.log(response)
return response
}, error => {
console.log('响应拦截器 失败 - 2号')
return Promise.reject(error)
})
// 发送请求
axios({
method: 'GET',
url: 'http://localhost:3000/posts'
}).then(response => {
console.log('自定义回调处理成功的结果')
}).catch(reason => {
console.log('自定义失败回调', reason)
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
7.9 axios 取消请求
- 设置 json-server 的延时:
npx json-server --watch db.json -d 2000
- 普通实例:
<body>
<button>发送请求</button>
<button>取消请求</button>
<script>
const btns = document.querySelectorAll('button')
// 2.声明全局变量
let cancel = null
btns[0].addEventListener('click', function () {
axios({
method: 'GET',
url: 'http://localhost:3000/posts',
// 1.添加配置对象的属性
cancelToken: new axios.CancelToken(c => {
// 3.将 c 的值赋值给 cancel
cancel = c
})
}).then(response => {
console.log(response)
})
})
btns[1].addEventListener('click', function () {
cancel()
})
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- 用户发送多个请求,取消重复的还在进行的请求:
<!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.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<button>发送请求</button>
<button>取消请求</button>
<script>
const btns = document.querySelectorAll('button')
// 2.声明全局变量
let cancel = null
btns[0].addEventListener('click', function () {
// 检测上一次请求是否已经完成
if (cancel !== null) {
cancel()
}
axios({
method: 'GET',
url: 'http://localhost:3000/posts',
// 1.添加配置对象的属性
cancelToken: new axios.CancelToken(c => {
// 3.将 c 的值赋值给 cancel
cancel = c
})
}).then(response => {
console.log(response)
// 将 cancel 值初始化设置
cancel = null
})
})
btns[1].addEventListener('click', function () {
cancel()
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45