第一章:原生 AJAX
1.1 AJAX 简介
- AJAX 全称为 Asynchronous Javascript And XML,即异步 JS 和 XML
- 通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新网页获取数据
- AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式
1.2 XML 简介
- XML:可扩展标记语言
- XML:被设计用来传输和存储数据
- XML 和 HTML 类似,不同点:HTML 中都是预定义标签,XML 中没有预定义标签,全是自定义标签,用来表示一些数据
- 现在已被 JSON 取代
1.3 AJAX 的特点
1.3.1 AJAX 的优点
- 可以无刷新页面与服务端进行通信
- 允许你根据用户事件来更新部分页面内容
1.3.2 AJAX 的缺点
- 没有浏览历史,不能回退
- 存在跨域问题(同源)
- SEO 不友好(爬虫获取不到信息)
1.4 HTTP 协议
1.4.1 HTTP 请求报文
- 请求行
method url
GET /product_detail?id=2
POST /login
- 多个请求头
Host: www.baidu.com
Cookie: BAIDUID=AD3B0FA706E; BIDUPSID=AD3B0FA706;
Content-Type: application/x-www-form-urlencoded 或者 application/json
- 请求体
username=tom&pwd=123
{"username": "tom", "pwd": 123}
1.4.2 HTTP 响应报文
- 响应状态行
status statusText
- 多个响应头
Content-Type: text/html;charset=utf-8
Set-Cookie: BD_CK_SAM=1;path=/
- 响应体
html 文本/json 文本/js/css/图片...
1.4.3 post 请求体参数格式
- Content-Type: application/x-www-form-urlencoded;charset=utf-8
用于键值对参数,参数的键值用=连接, 参数之间用&连接
例如: name=%E5%B0%8F%E6%98%8E&age=12
- Content-Type: application/x-www-form-urlencoded;charset=utf-8
用于 json 字符串参数
例如: {"name": "%E5%B0%8F%E6%98%8E", "age": 12}
- Content-Type: multipart/form-data
用于文件上传请求
1.4.2 常见的响应状态码
- 200 OK 请求成功。一般用于GET 与POST 请求
- 201 Created 已创建。成功请求并创建了新的资源
- 401 Unauthorized 未授权/请求要求用户的身份认证
- 404 Not Found 服务器无法根据客户端的请求找到资源
- 500 Internal Server Error 服务器内部错误,无法完成请求
1.4.3 不同类型的请求及其作用
- GET: 从服务器端读取数据(查)
- POST: 向服务器端添加新数据 (增)
- PUT: 更新服务器端已经数据 (改)
- DELETE: 删除服务器端数据 (删)
1.4.4 API 的分类
REST API: restful (Representational State Transfer (资源)表现层状态转化)
- 发送请求进行 CRUD 哪个操作由请求方式来决定
- 同一个请求路径可以进行多个操作
- 请求方式会用到 GET/POST/PUT/DELETE
非 REST API: restless
- 请求方式不决定请求的CRUD 操作
- 一个请求路径只对应一个操作
- 一般只有GET/POST
1.4.5 区别 一般 HTTP 请求 与 AJAX 请求
AJAX 请求 是一种特别的 HTTP 请求
对服务器端来说, 没有任何区别, 区别在浏览器端
浏览器端发请求: 只有 XHR 或 fetch 发出的才是 AJAX 请求, 其它所有的都是非 AJAX 请求
浏览器端接收到响应
- 一般请求: 浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/跳转页面
- AJAX 请求: 浏览器不会对界面进行任何更新操作, 只是调用监视的回调函数并传入响应相关数据
第二章:原生 AJAX 的基本使用 XHR
2.1 核心对象(XML)使用步骤
- 创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
- 设置请求信息
// 请求方式 method = get/post... url = https://www.gitee……
xhr.open(method, url);
//可以设置请求头,一般不设置
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
- 发送请求
xhr.send(body) //get请求不传 body 参数,只有post请求使用
- 接收响应(事件绑定,处理服务端返回的结果)
//xhr.responseXML 接收 xml格式 的响应数据
//xhr.responseText 接收 文本格式 的响应数据
xhr.onreadystatechange = function (){
// readyState 是 xhr对象中的属性, 表示状态 0 1 2 3 4
if(xhr.readyState == 4 && xhr.status == 200){
var text = xhr.responseText;
console.log(text);
}
}
4.1 readystate
0:未初始化
1:open 方法调用完毕
2:send 方法已经调用完毕
3:服务端返回的部分结果
4:服务器端返回的全部结果
2.2 GET 请求
- 服务端代码
@WebServlet("/login")
public class DemoService extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置响应头,通过一个头 Content-Type 告知客户端使用何种码表进行编码
// 旧:response.setHeader("Context-Type", "text/html;charset=UTF-8"); // 文本为 html 类型, 编码为 utf-8
response.setContentType("text/html;charset=UTF-8");
// 设置响应体
PrintWriter writer = response.getWriter();
writer.write("你好");
}
}
- 客户端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GET 请求方式</title>
</head>
<body>
<button>点击</button>
<h2 id="result"> </h2>
<script>
// 获取 buttom 元素
const btn = document.getElementsByTagName('button')[0];
// 绑定事件
btn.onclick = function () {
// 1、创建对象
const xhr = new XMLHttpRequest();
const res = document.getElementById("result")
// 2、初始化,设置请求方法和URL 2.1 设置 url 参数的一种方式
xhr.open('GET','http://localhost:8080/ajax01/succeed.html?name=tom&sex=男&age=12')
// 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){
// 处理结果 行 头 空行 体
// 1、响应行
console.log(xhr.status); // 状态码
console.log(xhr.statusText); // 状态字符串
console.log(xhr.getAllResponseHeaders()); // 所有响应头
console.log(xhr.response); // 响应体
// 设置 res 的文本
res.innerHTML = xhr.response;
}else {
console.log('失败');
}
}
}
}
</script>
</body>
</html>
2.3 post 请求
- 服务端代码
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/* 允许跨域的主机地址 */
response.setHeader("Access-Control-Allow-Origin", "*");
/* 允许跨域的请求方法GET, POST, HEAD 等 */
response.setHeader("Access-Control-Allow-Methods", "*");
// 设置响应头
response.setContentType("text/html;charset=UTF-8");
// 设置响应体
PrintWriter writer = response.getWriter();
writer.write("你好");
}
- 前端代码
<!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: 100px;
border: solid 1px #903;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
// 获取元素对象
const result = document.getElementById('result');
// 绑定事件
result.addEventListener("mouseover", function(){
// 1. 创建对象
const xhr = new XMLHttpRequest();
// 2. 初始化 设置类型(请求方式)与url
xhr.open('POST', 'http://127.0.0.1:8000/server');
// 3. 发送 设置请求参数(请求体)
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>
2.4 json 数据格式
- 服务端代码
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置响应头,通过一个头 Content-Type 告知客户端使用何种码表进行编码
// 旧:response.setHeader("Context-Type", "text/html;charset=UTF-8"); // 文本为 html 类型, 编码为 utf-8
response.setContentType("text/html;charset=UTF-8");
// 创建一个 json 对象
JSONObject obj = new JSONObject();
obj.put("name","张三");
// 将 json 对象转换为字符串
String str = JSON.toJSONString(obj);
// 设置响应体
PrintWriter writer = response.getWriter();
writer.write(str);
}
- 前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GET 请求方式</title>
</head>
<body>
<button>点击</button>
<h2 id="result"> </h2>
<script>
// 获取 buttom 元素
const btn = document.getElementsByTagName('button')[0];
const res = document.getElementById("result")
// 绑定事件
btn.addEventListener("mouseover", function () {
// 1 创建对象
const xhr = new XMLHttpRequest();
// *2*.(自动转换) 设置响应体数据的类型(自动转换)
xhr.responseType = 'json';
// 2 初始化 设置类型 与 URL
xhr.open("get","http://localhost:8080/ajax01/login")
// 3 发送 post 可以设置参数 任意格式,只要后端能处理就行
// xhl.send("123456")
// xhl.send("name=q|&age=12|set=女")
xhr.send()
// 设置请求头
// xhl.setRequestHeader('Content-Type','application/x-www-from-urlencoded');
// xhl.setRequestHeader('name','costom');
// 4 事件绑定
xhr.onreadystatechange = function () {
// 判断
if(xhr.readyState == 4){
if(xhr.status >= 200 && xhr.status < 300){
// 手动将字符串转成 json 对象
// let data = JSON.parse(xhl.response);
// 自动装换
console.log(xhr.response)
// 处理服务端返回的结果
res.innerHTML = xhr.response.name;
}else{
console.log("失败")
}
}
}
})
</script>
</body>
</html>
2.1 自动转换
// 2.(自动转换) 设置响应体数据的类型(自动转换)
xhr.responseType = 'json';
- 演示
2.5 请求超时与网络异常
// 超时设置 (2秒)
xhr.timeout = 2000;
// 超时回调
xhr.ontimeout = function(){
alert('网络超时,请稍后重试')
}
// 网络异常回调
xhr.onerror = function(){
alert('网络异常,请稍后重试')
}
2.6 取消请求
// 手动取消
xhr.abort()
2.7 请求重复发送问题
<script>
//获取元素对象
const btns = document.querySelectorAll('button');
let x = null;
//标识变量
let isSending = false; // 是否正在发送AJAX请求
btns[0].onclick = function(){
//判断标识变量
if(isSending) x.abort();// 如果正在发送, 则取消该请求, 创建一个新的请求
x = new XMLHttpRequest();
//修改 标识变量的值
isSending = true;
x.open("GET",'http://127.0.0.1:8000/delay');
x.send();
x.onreadystatechange = function(){
if(x.readyState === 4){
//修改标识变量
isSending = false;
}
}
}
// abort
btns[1].onclick = function(){
x.abort();
}
</script>
2.8 解决 IE 缓存问题
问题:在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。
解决方案:浏览器的缓存是根据url 地址来记录的,所以我们只需要修改url 地址即可避免缓存问题
xhr.open("get","/testAJAX?t="+Date.now());
2.9 AJAX 请求状态
- 0: 表示XMLHttpRequest 实例已经生成,但是open()方法还没有被调用
- 1: 表示send()方法还没有被调用,仍然可以使用setRequestHeader(),设定HTTP请求的头信息
- 2: 表示send()方法已经执行,并且头信息和状态码已经收到
- 3: 表示正在接收服务器传来的body 部分的数据
- 4: 表示服务器数据已经完全接收,或者本次接收已经失败了
2.10 API总结
- XMLHttpRequest():创建 XHR 对象的构造函数
- status:响应状态码值,如 200、404
- statusText:响应状态文本,如 ’ok‘、‘not found’
- readyState:标识请求状态的只读属性 0-1-2-3-4
- onreadystatechange:绑定 readyState 改变的监听
- responseType:指定响应数据类型,如果是 ‘json’,得到响应后自动解析响应
- response:响应体数据,类型取决于 responseType 的指定
- timeout:指定请求超时时间,默认为 0 代表没有限制
- ontimeout:绑定超时的监听
- onerror:绑定请求网络错误的监听
- open():初始化一个请求,参数为:(method, url[, async])
- send(data):发送请求
- abort():中断请求 (发出到返回之间)
- getResponseHeader(name):获取指定名称的响应头值
- getAllResponseHeaders():获取所有响应头组成的字符串
- setRequestHeader(name, value):设置请求头
第三章:jQuery 中的 AJAX
3.1 get 请求
$.get(url, [data], [callback], [type])
- url:请求的URL 地址
- data:请求携带的参数
- callback:载入成功时回调函数
- type:设置返回内容格式,xml, html, script, json, text, _default
例子
$('button').eq(0).click(function () {
// data 就是响应体
$.get('http://localhost:8080/ajax01/login',{a:100,b:200},function (data) {
console.log(data)
},'json')
})
3.2 post 请求
$.post(url, [data], [callback], [type])
- url:请求的URL 地址
- data:请求携带的参数
- callback:载入成功时回调函数
- type:设置返回内容格式,xml, html, script, json, text, _default
例子
$('button').eq(1).click(function () {
$.post('http://localhost:8080/ajax01/login',{a:100,b:200},function (data) {
console.log(data)
})
})
3.3 通用方法
$('button').eq(2).click(function () {
$.ajax({
// url 需要向那个资源请求
url: 'http://localhost:8080/ajax01/login',
// 参数 向服务端传数据
data: {a:100,b:200},
// 请求类型 GET/POST/PUT/DELETE
type: 'GET',
// 响应体结果,服务端返回的数据格式,不写就是字符串
dataType: 'json',
// 成功的回调 data 就是响应体
success: function (data) {
console.log(data)
},
// 超时时间
timeout: 2000,
// 失败的回调
error: function () {
console.log('出错啦!!!')
},
// 头信息
headers: {
c:300,
d:400
}
})
})
3.4 Axios 函数发送 AJAX 请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>axios 发送 AJAX请求</title>
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.js"></script>
</head>
<body>
<button>GET</button>
<button>POST</button>
<button>AJAX</button>
<script>
// https://github.com/axios/axios
const btns = document.querySelectorAll('button');
//配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000';
btns[0].onclick = function () {
//GET 请求
axios.get('/axios-server', {
//url 参数
params: {
id: 100,
vip: 7
},
//请求头信息
headers: {
name: 'atguigu',
age: 20
}
}).then(value => {
console.log(value);
});
}
btns[1].onclick = function () {
axios.post('/axios-server', {
username: 'admin',
password: 'admin'
}, {
//url
params: {
id: 200,
vip: 9
},
//请求头参数
headers: {
height: 180,
weight: 180,
}
});
}
btns[2].onclick = function(){
axios({
//请求方法
method : 'POST',
//url
url: '/axios-server',
//url参数
params: {
vip:10,
level:30
},
//头信息
headers: {
a:100,
b:200
},
//请求体参数
data: {
username: 'admin',
password: 'admin'
}
}).then(response=>{
//响应状态码
console.log(response.status);
//响应状态字符串
console.log(response.statusText);
//响应头信息
console.log(response.headers);
//响应体
console.log(response.data);
})
}
</script>
</body>
</html>
3.5 fetch 函数发送 AJAX 请求
<script>
//文档地址
//https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch
const btn = document.querySelector('button');
btn.onclick = function(){
fetch('http://127.0.0.1:8000/fetch-server?vip=10', {
//请求方法
method: 'POST',
//请求头
headers: {
name:'atguigu'
},
//请求体
body: 'username=admin&password=admin'
}).then(response => {
// return response.text();
return response.json();
}).then(response=>{
console.log(response);
});
}
</script>