学习AJAX

AJAX学习

1.原生AJAX

1.1 AJAX简介

异步的JS和XML

在浏览器中向服务器发送异步的请求,无刷新地获取数据

1.2 XML简介

可扩展标记语言,可用来传输和存储数据,没有预定义标签,全是自定义标签

例如有一条学生数据:

1
2
3
4
5
<student>
<name>monica</name>
<age>18</age>
<gender>female</gender>
</student>

现在已经被JSON取代

1
{"name":"monica","age":18,"gender":"female"}

1.3 AJAX的特点

1.3.1 AJAX优点

无需刷新页面与服务器通信

允许根据用户事件更新部分页面内容

1.3.2 AJAX缺点

没有浏览历史,不能回退

存在跨域问题

SEO(搜索引擎优化)不友好,爬虫爬取不到

1.4 HTTP报文

可在network中查看

请求报文

1
2
3
4
5
6
7
8
9
行	POST /server  HTTP/1.1

头 Host: 127.0.0.1:8000

User-Agent: Chrome 83

空行

体 username=monica&password=123

响应报文

1
2
3
4
5
6
7
8
9
行	 HTTP/1.1 200 OK

头 Content-Type: text/html; charset=utf-8

​ Content-Length: 15

空行

体 hello,ajax POST

1.5 express框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1.引入express
const express = require('express');
const { request } = require('http');

// 2.创建应用对象
const app = express();

// 3.创建路由规则
// request 是对请求报文封装,response 是对响应报文封装
app.get('/', (request, response) => {
response.send('hello,express')
})

// 4.监听端口,启动服务
app.listen(8000, () => {
console.log('server starts,listening on 8000...');
})

1.6.1 AJAX案例_请求的基本操作

GET.html

1
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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ajax get请求</title>
<style>
#result {
width: 300px;
height: 200px;
border: 1px solid pink;
}
</style>
</head>

<body>
<button>点我发送请求</button>
<div id="result"></div>
<script>
// 获取对象
const btn = document.querySelector('button');
const result = document.querySelector('#result');
// 绑定按钮点击事件
btn.onclick = function () {
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化
xhr.open('GET', 'http://localhost:8000/server');
// 3.发送
xhr.send();
// 4.事件绑定,处理服务端返回的结果
// 只要 readyState 属性发生变化,就会调用相应的处理函数
// XMLHttpRequest.onreadystatechange 会在 XMLHttpRequest 的readyState 属性发生改变时触发 readystatechange 事件的时候被调用。
xhr.onreadystatechange = function () {
// 判断当服务端返回了所有的结果
if (xhr.readyState === 4) {
// 响应成功
if (xhr.status >= 200 && xhr.status < 300) {
// 响应
// console.log(xhr.status);
// console.log(xhr.statusText);
// console.log(xhr.getAllResponseHeaders());
// console.log(xhr.response);

// 处理结果
result.innerHTML = xhr.response;
}
}
}

};
</script>
</body>

</html>

server.js

1
2
3
4
5
6
7
8
9
10
11
12
const express=require('express');
const app=express();
// 访问路由为localhost:8000/server
app.get('/server',(request,response)=>{
// 设置响应头,允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
// 设置响应体
response.send('hello,ajax')
})
app.listen(8000,()=>{
console.log('server running on 8000...');
})

1.6.2 设置请求参数

1
2
3
// 设置请求参数
xhr.open('GET', 'http://localhost:8000/serverusername=monica&password=123&gender=female');

1.6.3 发送POST请求

POST.html

1
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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ajax POST 请求</title>
<style>
.result {
width: 400px;
height: 200px;
border: 1px solid pink;
}
</style>
</head>

<body>
<!-- 鼠标悬浮于div上发送POST请求,并在div中呈现响应结果 -->
<div class="result"></div>
<script>
// 获取对象
const result = document.querySelector('.result');
// 绑定事件
result.addEventListener('mouseover', function () {
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化
xhr.open('POST', 'http://127.0.0.1:8000/server');
// 3.发送
// 可以设置请求体
// xhr.send();
xhr.send('a=100&b=200&c=300');
// 4.事件绑定,处理返回结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response;
}
}
}
});
</script>
</body>

</html>

server.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const express=require('express');
const app=express();
// 访问路由为localhost:8000/server
// 对应GET请求
app.get('/server',(request,response)=>{
// 设置响应头,允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
// 设置响应体
response.send('hello,ajax')
})

// 对应POST请求
app.post('/server',(request,response)=>{
// 设置响应头,允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
// 设置响应体
response.send('hello,ajax POST')
})

app.listen(8000,()=>{
console.log('server running on 8000...');
})

1.6.4 POST设置请求体

1
2
3
4
// 3.发送
// 可以设置请求体
// xhr.send();
xhr.send('a=100&b=200&c=300');

1.6.5 设置请求头信息

1
2
3
4
// 2.初始化
xhr.open('POST', 'http://127.0.0.1:8000/server');
// 设置请求头信息
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

1.6.6 服务端对JSON数据的响应

index.html

1
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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>响应JSON</title>
<style>
.result {
width: 400px;
height: 200px;
border: 1px solid skyblue;
}
</style>
</head>

<body>
<div class="result"></div>
<script>
// 获取对象
const result = document.querySelector('.result');
// 绑定事件
window.onkeydown = function () {
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化
// 设置返回数据类型,可自动转换JSON为对象
xhr.responseType = "json";
xhr.open('GET', 'http://127.0.0.1:8000/server');
// 设置请求头信息
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

// 3.发送
// 可以设置请求体
// xhr.send();
xhr.send('a=100&b=200&c=300');
// 4.事件绑定,处理返回结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 自动转换,注意初始化前设置xhr的返回数据类型
result.innerHTML = xhr.response.name;
}
}
}
};
</script>
</body>

</html>

sever.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const express = require('express');
const app = express();
// 访问路由为localhost:8000/server
// 对应GET请求
app.get('/server', (request, response) => {
// 设置响应头,允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 响应一个数据
const data = { "name": "monica" }
const str = JSON.stringify(data)
// 设置响应体
response.send(str)
})

// 对应POST请求
app.post('/server', (request, response) => {
// 设置响应头,允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应体
response.send('hello,ajax POST')
})

app.listen(8000, () => {
console.log('server running on 8000...');
})

1.7 请求超时和网络异常处理

1
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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ajax get请求</title>
<style>
#result {
width: 300px;
height: 200px;
border: 1px solid pink;
}
</style>
</head>

<body>
<button>点我发送请求</button>
<div id="result"></div>
<script>
// 获取对象
const btn = document.querySelector('button');
const result = document.querySelector('#result');
// 绑定按钮点击事件
btn.onclick = function () {
// 1.创建对象
const xhr = new XMLHttpRequest();
// 超时设置为 2s
xhr.timeout=2000;
// 超时回调
xhr.ontimeout=function(){
alert('请求超时,请稍后再试')
};
// 网络异常回调
xhr.onerror=function() {
alert('网络好像出问题了');
}
// 2.初始化
// 设置请求参数
xhr.open('GET', 'http://localhost:8000/server');
// 3.发送
xhr.send();
// 4.事件绑定,处理服务端返回的结果
// 只要 readyState 属性发生变化,就会调用相应的处理函数
// XMLHttpRequest.onreadystatechange 会在 XMLHttpRequest 的readyState 属性发生改变时触发 readystatechange 事件的时候被调用。
xhr.onreadystatechange = function () {
// 判断当服务端返回了所有的结果
if (xhr.readyState === 4) {
// 响应成功
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果
result.innerHTML = xhr.response;
}
}
}

};
</script>
</body>

</html>

1.8 取消请求

1
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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ajax 取消请求</title>
<style>
#result {
width: 300px;
height: 200px;
border: 1px solid pink;
}
</style>
</head>

<body>
<button>点我发送请求</button>
<button>点我取消请求</button>
<script>
// 获取对象
const sendbtn = document.querySelectorAll('button')[0];
const cancelbtn = document.querySelectorAll('button')[1];
// 标识是否正在发送请求变量
let isPending = false;
let xhr = null;
// 绑定按钮点击事件
sendbtn.onclick = function () {
// 如果正在发送,则取消该请求,创建新请求
if (isPending) {
xhr.abort();
}
// 1.创建对象
xhr = new XMLHttpRequest();
// 2.初始化
// 设置请求参数
xhr.open('GET', 'http://localhost:8000/server');
// 3.发送
xhr.send();
isPending = true;
// 4.事件绑定,处理服务端返回的结果
xhr.onreadystatechange = function () {
// 判断当服务端返回了所有的结果
if (xhr.readyState === 4) {
isPending = false;
}
}

};
cancelbtn.onclick = function () {
xhr.abort();
}
</script>
</body>

</html>

2.axios

使用axios发送ajax请求

1
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
74
75
76
77
78
79
80
81
82
83
84
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>axios</title>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.7.2/axios.js"></script>
</head>

<body>
<button>GET</button>
<button>POST</button>
<button>AJAX</button>

<script>
let btns = document.querySelectorAll('button');
// 配置baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000';
btns[0].onclick = function () {
axios.get('/axios-server', {
// url参数
params: {
name: "monica",
vip: "yes"
},
// 请求头信息
headers: {
a: 100,
b: 200
}
}).then(value => {
console.log(value);
})
};
btns[1].onclick = function () {
axios.post('/axios-server',
{
// 请求体信息
school: 'UESTC',
age: '19'
},
{
// 配置参数,包括url参数和请求头信息
params: {
name: "monica",
vip: "yes"
},
headers: {
a: 100,
b: 200
}
})
.then(response => {
console.log(response.data);
})
}
btns[2].onclick = function () {
axios({
// 请求类型
method: 'POST',
// url
url: '/axios-server',
// url参数
params: {
name: 'monica',
age: '19'
},
// 头信息
headers: {
a: 100,
b: 200
},
// 请求体参数
data: {
student: 'tom',
school: 'UESTC'
}
})
}
</script>
</body>

</html>

3.使用fetch函数发送ajax请求

1
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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>fetch</title>
</head>

<body>
<button>POST</button>

<script>
let btn = document.querySelector('button');
btn.onclick = function () {
fetch('http://127.0.0.1:8000/fetch-server', {
// 请求方法
method: 'POST',
// 请求头
headers: {
a: 100,
b: 200
},
// 请求体
body: {
name: 'monica',
age: 19
}
}).then(response => {
console.log(response);
})
};

</script>
</body>

</html>

4.跨域

4.1 同源策略

同源:协议、域名、端口号必须完全相同

AJAX默认遵循同源策略

违背同源策略就是跨域

4.2 jsonp

4.3 CORS

新增一组响应头

1
response.setHeader('Access-Control-Allow-Origin', '*')

一般开发中加上

1
2
3
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Headers', '*')
response.setHeader('Access-Control-Allow-Method', '*')

学习AJAX
http://example.com/2024/09/24/学习AJAX/
作者
monica
发布于
2024年9月24日
许可协议