2021/8/6
一、原生AJAX
1.1 AJAX 简介
AJAX 全称为 Asynchronous JavaScript And XML ,就是异步的 JS 和 XML。 通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。 AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式
1.2 XML 简介
XML: 可扩展标记语言 XML:被设计用来传输和存储数据(补:HTML是用来在网页中显现数据的) XML 和 HTML 类似,不同的是 HTML 中都是预定义标签(已经定义好的标签),而XML中没有预定义标签,全都是自定义标签,用来表示一些数据
例如说我有一个学生数据
name = "孙悟空"; age = 18;gender = "男";
用XML表示:
<student>
<name>孙悟空</name>
<age>18</age>
<gender>男</gender>
</student>
现在已经被 JSON 取代了
用JSON表示:
{"name": "孙悟空", "age": 18, "gender": "男"}
1.3 AJAX的特点
1.3.1 AJAX 的优点
- 可以无需刷新页面与服务器端进行通信
- 允许你根据用户事件来更新部分页面内容
1.3.2 AJAX 的缺点
- 没有浏览历史,不能回退
- 存在跨域问题
- SEO(搜索引擎优化)不友好
二、Express框架的简单介绍(下载完node.js之后才能使用Express)
-
- 在命令行工具中安装 Express
$ npm install express -
- express的基本使用方式:
const express = require('express');
const app =express();
app.get('/', (request, response) => {
response.send('HELLO EXPRESS');
})
app.listen(8000, () => {
console.log("服务已经启动,8000端口监听中......");
})
案例分析
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 GET 请求</title>
<style>
#result {
width: 200px;
height: 200px;
border: solid 1px #90b;
margin-top: 20px;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
</body>
<script>
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById('result');
btn.onclick = function () {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send();
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;
} else {
}
}
}
}
</script>
</html>
当请求方式为 GET 时,它的请求参数可以直接在 url 后面设置,需要在中间加上一个**?,参数之间用&** 隔开 如: xhr.open('GET', 'http://127.0.0.1:8000/server?name=zhangsan&age=18');

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>AJAX POST 请求</title>
<style>
#result {
width: 200px;
height: 200px;
border: solid 1px blue;
}
</style>
</head>
<body>
<div id="result"></div>
</body>
<script>
const result = document.getElementById('result');
result.addEventListener('mouseover', function () {
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >=200 && xhr.status < 300) {
result.innerHTML = xhr.response;
}
}
}
})
</script>
</html>
当请求方式为POST 时,它的请求参数需要加上send() 方法中,如xhr.send('name=xyh&age=22'); 
三、POST 请求体设置
在前面的案例分析中,我们设置了请求行、请求体,也知道了不同请求方式的请求参数的设置,现在来记录一下请求头的设置 setRequestHeader() 可用来设置请求头,
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://127.0.0.1:8000/server');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('name=xyh&age=22');

四、服务器端传递JSON数据处理
app.all('/json-server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*');
const datas = {
name: 'xyh'
};
let str = JSON.stringify(datas);
response.send(str);
});
对于客户端对服务器端返回的JSON数据有两种处理方式
1. 手对处理
<script>
const result = document.getElementById('result');
window.onkeydown = function () {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/json-server');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState ===4) {
if (xhr.status >= 200 && xhr.status < 300) {
let datas = JSON.parse(xhr.response);
result.innerHTML = datas.name;
}
}
}
}
</script>
1. 自动转换
自动转换相对于手动转换要方便很多,只需要设置响应体的数据类型为json xhr.responseType = 'json';
<script>
const result = document.getElementById('result');
window.onkeydown = function () {
const xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open('GET', 'http://127.0.0.1:8000/json-server');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState ===4) {
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response.name;
}
}
}
}
</script>
五、AJAX 关于请求的常见问题
5.1 AJAX请求超时和网络异常处理
app.get('/delay', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*');
setTimeout (() => {
response.send('延时响应');
}, 3000)
});
btn.addEventListener('click', function () {
const xhr = new XMLHttpRequest();
xhr.timeout = 2000;
xhr.ontimeout = function () {
alert('网络异常,请稍后重试');
}
xhr.onerror = function () {
alert('您的网络似乎出了一些问题,请检查!');
}
xhr.open('GET', 'http://127.0.0.1:8000/delay');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >=200 && xhr.status < 300) {
result.innerHTML = xhr.response;
}
}
}
});
可以看见在sever.js中可以 使用定时器,延时了3秒,html文件中设置了2秒的限制,如果在2秒之内没有完成响应,就取消请求,同时设置了超时回调事件。
5.2 手动取消请求操作
在上面的延时响应中,使用了xhr.timeout = 2000; 来进行自动取消请求操作。这时我们使用abort() 方法来完成手动取消请求
<body>
<button>点击发送请求</button>
<button>取消发送请求</button>
</body>
<script>
const btns = document.getElementsByTagName('button');
let xhr = null;
btns[0].onclick = function () {
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/delay');
xhr.send();
}
btns[1].onclick = function () {
xhr.abort();
}
</script>
5.3 AJAX 请求重复问题解决
在用户使用过程中,难免会存在重复请求(比如想申请一个页面时,因网络卡顿,过多去点击请求按钮),而这也加重了服务器端的工作。以下用一个标识变量的方法就可以解决这个问题。
<script>
const btns = document.getElementsByTagName('button');
let xhr = null;
let isSending = false;
btns[0].onclick = function () {
if (isSending) xhr.abort();
xhr = new XMLHttpRequest();
isSending = true;
xhr.open('GET', 'http://127.0.0.1:8000/delay');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
isSending = false;
}
}
}
</script>
六、jQuery 中发送AJAX请求
在jQuery中发送AJAX有三种方式,分别是get,post, 和一种通用的方式,其中使用回调函数来接收返回的数据
app.all('/jquery-server', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*');
const data = {name: 'xhy', age: 18};
response.send(JSON.stringify(data));
});
<body>
<button>发送请求GET</button>
<button>发送请求POST</button>
<button>通过请求AJAX</button>
</body>
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$('button').eq(0).click(function () {
$.get('http://127.0.0.1:8000/jquery-server', {a:100, b:300}, function (data) {
console.log(data);
},'json')
})
$('button').eq(1).click(function () {
$.post('http://127.0.0.1:8000/jquery-server', {a:100, b:300}, function (data) {
console.log(data);
})
})
$('button').eq(2).click(function () {
$.ajax({
url: 'http://127.0.0.1:8000/jquery-server',
data: {a: 100, b: 200},
type: 'GET',
dataType: 'json',
success: function (data) {
console.log(data);
},
timeout: 2000,
error: function () {
console.log('出错了!!');
}
})
})
</script>
七、 axios 发送AJAX请求
7.1 (get / post)请求方式
axios支持promise,接收返回数据时使用.then()
<body>
<button>发送请求GET</button>
<button>发送请求POST</button>
<button>AJAX</button>
</body>
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
const btn = document.querySelectorAll('button');
axios.defaults.baseURL = 'http://127.0.0.1:8000';
btn[0].onclick = function () {
axios.get('/axios-server', {
params: {
id: 51802121013,
vip: 7
},
headers: {
name: 'xyh',
age: 21
}
})
.then(function (data) {
console.log(data);
})
}
btn[1].onclick = function () {
axios.post('/axios-server', {
username: 'admin',
password: '123456'
},
{
params: {
id: 51802121013,
vip: 7
},
headers: {
name: 'xyh',
age: 21
}
})
}
</script>
仔细观察上面的代码,可以发现get请求方式和 post请求方式的格式不一样。经过官方文档的查看,发现post请求方式,如果有请求体(data),则放在url 和 config中间 
7.2 axios 通用发送AJAX请求方式
类似于jquery 通用发送AJAX请求方式
btn[2].onclick = function () {
axios({
method: 'GET',
url: 'http://127.0.0.1:8000/axios-server',
params: {
id: 51802121013,
vip: 7
},
headers: {
name: 'xyh',
age: 21
},
data: {
username: 'admin',
password: '123456'
}
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
}
八、跨域
8.1 同源策略(说白了就是在同一个服务器)
同源策略(Same-Origin Policy)最早是由Netscape公司提出的,是浏览器的一种案例策略。 同源: 协议、域名、端口号、必须完全相同 违背同源策略就是跨域
8.2 如何解决跨域
8.2.1 JSONP
1) JSONP 是什么 JSONP(JSON with Padding)是一个非官方的跨域解决方案,纯粹凭程序员的聪明才智开发出来,只支持 get 请求
2)JSONP 怎么工作的? 在网页有一些标签天生具有跨域能力,比如: img link script JSONP 就是利用 script 标签的跨域能力来发送请求的
3)使用JSONP的使用
<style>
#result {
width: 300px;
height: 100px;
border: solid 1px #78a;
}
</style>
</head>
<body>
<div id="result"></div>
</body>
<script>
function handle(data) {
const result = document.getElementById('result');
result.innerHTML = data.name;
}
</script>
<script src="http://127.0.0.1:8000/jsonp-server"></script>
app.all('/jsonp-server',(request, response) => {
const data = {
name: '尚硅谷atguigu'
};
let str = JSON.stringify(data);
response.end(`handle(${str})`);
});
4) JSONP 使用小案例——原生 (判断用户名是否存在,不存在则提醒用户)
<body>
用户名<input type="text" id="username"></input>
<p></p>
<script>
const input = document.querySelector('input');
const p = document.querySelector('p');
function handle(data) {
input.style.border = "solid 1px red";
p.innerHTML = data.msg;
}
input.onblur = function() {
let username = this.value;
const script = document.createElement('script');
script.src = "http://127.0.0.1:8000/check";
document.body.appendChild(script);
}
</script>
</body>
app.all('/check',(request, response) => {
const data = {
exist: 1,
msg: '用户名已经存在'
};
let str = JSON.stringify(data);
response.end(`handle(${str})`);
});
|