一,准备知识
1、Ajax优缺点
优点:
-
可以不刷新页面与服务器通信
-
可以根据用户事件更新部分页面内容
缺点:
-
无浏览记录,无法回退
-
存在跨域问题
-
SEO不友好
2、HTTP协议
超文本传输协议,规定了浏览器与万维网服务器之间的交换规则,主要约定了两块内容:请求和响应。
①.请求报文(重点:记忆格式与参数就ok了)
四部分:
请求行(包含三部分:请求类型、URL路径、HTTP协议版本);
请求头;
空行;
请求体;
行: POST /s?ie=utf-8 HTTP/1.1
头: Host: baidu.com
Cookies: name = wd
Content-type: application/x-www-form-urlencoded
User-Agent: Chrome 83
格式:名字:空格 值
空行
请求体:get请求为空 post请求可以不为空
比如:username = admin&password = admin
②.响应报文
行:HTTP/1.1 200 OK (协议版本 状态码 状态字符串
头 类型 长度
空行
体 返回结果
3、浏览器控制台查看报文
-
F12
-
Network
-
刷新-会列出来网页发送的所有的请求
-
点第一个请求
-
会出现Headers Preview Respoonse(响应体在这看) Initiator Timing Cookies
重点是 Headers(重点Response Headers:响应头 Request Headers:请求头) Response
请求报文查看:Headers下面的请求头Request Header +请求体 Form Data 响应报文查看 Headers下面的Response Headers和Response
-
使用get请求有参数的时候 在Headers里面还会有一个Query String Parameters放参数的地方;
4、安装Node.js Express框架
why:Ajax会给服务端发请求,需要一个服务端,而Express是基于Node的一个服务端框架,只需要掌握基本使用就ok了
安装完Node.js(node安装省略,很简单),后安装express:::
-
在vscode软件项目最外层文件中,打开终端
-
终端输入代码初始化:npm init --yes
-
安装express框架:npm i express
-
引入express
//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 端口监听中....");
});
5.执行脚本:node express基本使用.js
6.浏览器查看http://127.0.0.1:8000/,输出HELLO EXPRESS
二、Ajax基本操作
1、点击获取数据的案例(GET)
案例:HTML页面有一个div框 有一个button框 点击按钮 使接收到的请求数据返回到div框内
①准备工作:
准备:1、HTML页面文件
<!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:200px;
height:100px;
border:solid 1px #90b;
}
</style>
</head>
<body>
<button id = "btn">点击发送请求</button>
<div id="result"></div>
<script>
//获取button元素
const btn = document.querySelector('#btn');
const result = document.querySelector('#result')
</script>
</body>
</html>
2、express.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 端口监听中....");
});
特别注意:
路由设置./server是指浏览器向服务器发送请求的时候,ulr路径也就是请求行的第二行内容,路径是/server,则会执行后面的回调函数,由response执行响应
响应头的设置response.setHeader('Access-Control-Allow-Origin','*'); 代表设置可以跨域
②创建一个Ajax对象
<!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:200px;
height:100px;
border:solid 1px #90b;
}
</style>
</head>
<body>
<button id="btn">点击发送请求</button>
<div id="result"></div>
<script>
//获取button元素
const btn = document.querySelector('#btn');
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. 事件绑定 处理服务端返回的结果
// on when 当....时候
// readystate 是 xhr 对象中的属性, 表示状态 0 1 2 3 4
// change 改变
xhr.onreadystatechange = function(){
//判断 (服务端返回了所有的结果)
if(xhr.readyState === 4){
//判断响应状态码 200 404 403 401 500
// 2xx 成功
if(xhr.status >= 200 && xhr.status < 300){
//处理结果 行 头 空行 体
//响应
// console.log(xhr.status);//状态码
// console.log(xhr.statusText);//状态字符串
// console.log(xhr.getAllResponseHeaders());
//所有响应头
// console.log(xhr.response);//响应体
//设置 result 的文本
result.innerHTML = xhr.response;
}else{
}
}
}
})
</script>
</body>
</html>
③如何给Ajax请求中设置url参数
原始代码见上面代码块28 29行
//原始代码
xhr.open('GET', 'http://127.0.0.1:8000/server');
//如何传参
//直接在设置url后面+参数,问号分割,参数名字=值,然后&连接下一个参数和值
xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
//如何在Chrome调试查看参数-F12-Network-Headers-Query String Parameters-可以查看参数是否存在
2、AJAX的POST请求案例
页面中一个div框,鼠标放在框内的时候,发送一个POST请求,将响应体在div内部进行呈现
①准备工作:
HTML方面:设置div框 绑定元素 绑定事件
<!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:200px;
height:100px;
border:solid 1px #903;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
//获取元素对象
const result = document.getElementById("result");
//绑定事件
result.addEventListener("mouseover", function(){
//后面写
});
</script>
</body>
</html>
JS方面:
路由规则 方法改为post(小写)
app.post('/server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应体
response.send('HELLO AJAX POST');
});
②创建AJAX对象
下面的代码放在上面的function中
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化 设置类型与 URL
xhr.open('POST', 'http://127.0.0.1:8000/server');
//设置请求头,open后面这个方法是设置请求头,接受两个参数,一个是头的名字,第二个是值,后面会讲,跟本小节案例无关
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//3. 发送
xhr.send();
//4. 事件绑定
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
//处理服务端返回的结果
result.innerHTML = xhr.response;
}
}
}
③POST请求中如何设置参数
在页面文件xhr.send()的send方面中设置参数,见上面代码块的第8行
xhr.send('a=100&b=200&c=300');
//请求体的这些参数 可以写任意格式的参数和值,如
//xhr.send('a:100&b:200');
//xhr.send('12345')
3、AJAX如何设置请求头信息
见上面代码块5-6行
//HTML文件中的操作
//设置自带的头信息属性
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//加入自定义的头信息,比如以下
xhr.setRequestHeader('name','ycc');
//上面这行代码在浏览器中运行会报错,浏览器有安全机制,name属性是我们单独加的自定义属性,因此会报错。如果需要解决报错这个问题,需要在后端文件中,设置响应头的地方加上下面这行代码,而在实际开发中,这种事一般是后端人员的工作
//JS文件中的操作
//下面这行代码表示所有类型的头信息浏览器都可以接收
response.setHeader('Access-Control-Allow-Headers','*')
//还需要把js文件里的路由规则的app.post改成app.all
4、服务端响应JSON数据
why:在开发中 大部分时候都是返回的JSON格式的数据,因此这块必须掌握,知道结果怎么处理
案例:HTML中有一个div框,键盘按下任意按键,就会对服务器发送请求,将响应数据中的值在div中呈现
HTML部分
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box{
height: 200px;
width: 300px;
border: 1px solid red;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
const box = document.querySelector('#box');
window.addEventListener('keydown',()=>{
//1.创建Ajax实例
const xhr = new XMLHttpRequest();
//2.设置响应体数据的类型,接收到的数据类型为json 后面方便直接调用,和下面的方法一不能并存
xhr.responseType = 'json';
//3.初始化,发送请求,获取路径
xhr.open('GET','http://127.0.0.1:8000/json-server');
//4.发送send请求
xhr.send();
//5.事件绑定,当服务器响应结束后应该进行的操作
xhr.onreadystatechange = function(){
//判断是否服务器到第四个阶段
if(xhr.readyState === 4){
//判断是否状态码为2**,成功状态码
if(xhr.status >= 200 & xhr.status <300){
//进行json数据操作,得到服务器响应数据
//测试是否得到响应体
// console.log(xhr.response);
// box.innerHTML = xhr.response;
// /*方法一:手动数据转换,xhr.response是一个json格式字符串
// 想要获取其中的一个数据就比较麻烦,可以借助下面的方法转换成一个对象*/
// let data = JSON.parse(xhr.response);
// // console.log(data);
// box.innerHTML = data.age;
// 方法二:自动转换数据,23行取消注释,设置接收数据类型为json格式,自动转换成对象
box.innerHTML = xhr.response.age;
}
}
}
})
</script>
</body>
</html>
易错点:①:25行http://127.0.0.1:8000/json-server中的//不能少 ②23行的代码跟41行的Json.parse不能一起使用
js部分
//一、JSON需要的js文件
//1.引入express
const express = require('express');
//2.创建应用
const app = express();
//3.创建理由规则-Json响应
app.all('/json-server',(request,response) => {
//设置允许跨域的响应头
response.setHeader('Access-Control-Allow-Origin','*');
//设置允许自定义响应头
response.setHeader('Access-Control-Allow-Headers','*');
//响应一个数据
const data ={
age: 26
};
//对对象进行字符串转化,因为最后的send方法只能接受字符串类型
let str = JSON.stringify(data);
//设置响应体,发送数据
response.send(str);
});
//监听端口启动服务
app.listen(8000, ()=>{
console.log("服务已经启动, 8000 端口监听中....");
});
5、下载nodemon插件
why:AJAX练习学习,会经常修改服务端代码,nodemon插件可以帮助在服务端代码改变的时候,自动重启
直接在vscode终端进行操作安装:npm install -g nodemon
使用方法:nodemon server.js启动软件
6、IE缓存问题
IE浏览器和AJAX交互的时候,会把交互的结果进行缓存,下一次再触发事件的时候,并不会重新使用Ajax发送请求,而是直接从本地缓存调取数据,因此,需要解决这个问题,一般而言就是在初始化发送请求的URL后面加一个参数
//原始代码
xhr.open('Get','http://127.0.0.1:8000/ie')
//修改之后的代码
xhr.open('Get','http://127.0.0.1:8000/ie?t='Date.now())
7、请求超时与网络异常响应
主要依靠在js文件中使用 SetTimeOut
主要代码:
1、超时设置,超过多少毫秒就算超时,取消发送请求
xhr.timeout = 2000 ;
2、超时回调,请求超时后执行后面的回调函数
xhr.ontimeout = function(){
//执行操作,比如弹窗提醒 }
3、网络异常回调(如何测试,浏览器F12-Network-Online)
xhr.onerror = function(){}
案例:按钮+div,①点击按钮,如果超时就取消发送请求并执行回调弹窗提醒 ②测试网络异常情况下,弹窗提醒
准备:因为要测试延迟,我们可以以2秒钟算超时,那么需要再服务端js中加一个定时器,比如三秒钟发送响应报文
开干:
HTML:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>延时响应测试</title>
<style>
#box{
border: 1px solid red;
width: 300px;
height: 200px;
}
</style>
</head>
<body>
<button id="btn">点击发送数据</button>
<div id="box"></div>
<script>
//绑定点击事件
const btn = document.querySelector('#btn');
const box = document.getElementById('box');
btn.addEventListener('click',()=>{
//创建AJAX实例
const xhr = new XMLHttpRequest();
//初始化,设置获取方法和路径
xhr.open('GET','http://127.0.0.1:8000/delay');
//发送请求
xhr.send();
//超时设置,超过多少毫秒就算超时,取消发送请求
xhr.timeout = 2000;
//超时回调,请求超时后执行后面的回调函数
xhr.ontimeout = function(){
alert('请求超时');
}
//网络异常回调
xhr.onerror = function(){
alert('网络异常')
}
//绑定服务器事件
xhr.onreadystatechange = function(){
//判断是否到服务器第四个阶段
if(xhr.readyState === 4){
//判断是否返回2**成功状态码
if(xhr.status >= 200 & xhr.status < 300){
//进行操作响应,根据服务端的响应,延迟三秒后出现
box.innerHTML = xhr.response;
}
}
}
})
</script>
</body>
</html>
JS:
//1.引入express
const express = require('express');
//2.创建应用
const app = express();
//创建路由规则
app.get('/delay',(request,response)=>{
//设置允许跨域的响应头
response.setHeader('Access-Control-Allow-Origin','*');
//设置一个延时发送响应,3秒发送一个请求到浏览器
setTimeout(()=>{
response.send('延迟了三秒的数据')
},3000)
})
//监听端口启动服务
app.listen(8000, ()=>{
console.log("服务已经启动, 8000 端口监听中....");
});
8、AJAX取消请求
借助方法:xhr.abort
案例:两个按钮,一个按钮发送请求,一个按钮取消请求
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>点击发送</button>
<button>点击取消</button>
<script>
//获取元素 绑定事件
const btns = document.querySelectorAll('button');
//给第一个按钮绑定一个发送ajax请求的事件
let x = null;
btns[0].onclick = function(){
//创建ajax实例
x = new XMLHttpRequest();
x.open('GET','http://127.0.0.1:8000/delay');
x.send()
}
//给第二个按钮绑定一个ajax取消事件
btns[1].addEventListener('click',()=>{
x.abort();
})
</script>
</body>
</html>
9、性能优化,重复发送请求
案例:当用户多次点击一个事件,发送多次请求的时候,服务器会接收到很多相同请求,不利于性能优化,
需求实现:因此,我们在发送请求的时候,可以检测一下,是否之前发送过相同的请求,如果发送过相同的请求,可以把之前发送的请求取消掉,重新发送一个新的请求
代码分析:需要判断是否有正在发送的ajax请求,如果有的话,那么就取消,然后重新发送。因此需要在外部声明一个标识变量,来存储是否有ajax请求,先传入false的值,表示没有,然后进行元素事件绑定,判断是否标识变量为true,是true的话,执行abort方法,然后创建ajax实例,将变量值改为true,然后发送ajax请求,然后进行服务器事件绑定,在服务器事件绑定内部,当readyState状态为4的时候,即服务器响应完成之后,整个ajax交互完成,修改标识变量为false。详情代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>发送请求</button>
<script>
const btn = document.querySelector('button');
//13行代码易错点,因为会反复创建ajax实例,因此不能在下面绑定事件内部const创建
let xhr =null;
let isSending = false;
btn.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>
</body>
</html>
易错点13行变量
16万+

被折叠的 条评论
为什么被折叠?



