AJAX
AJAX
第一章 原生AJAX
1.1ajax简介
AJAX全称是asynchronous JavaScript and xml ,就是异步的js和xml
通过ajax可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据
ajax不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式
按需加载,需要的话就加载,不要的话就不用加载。
比如朋友圈,用户不需要刷新就可以获取新的信息。
1.2xml简介
xml 可拓展标记语言
xml被设计来传输和存储数据
xml和html类似,不同的html中都是预定义标签,而xml中没有预定义标签,全都是自定义标签,用来表示一些数据。
预定义标签:提前定义好的,比如h2标签p标签等
1.3json格式
现在已经json取代了
1.4ajax的特点
1.4.1优点
- 可以无需刷新页面与服务器端进行交互。
- 允许根据用户事件来更新部分页面的内容
1.4.2缺点
-
没有浏览历史,不能回退
-
存在跨域问题
在这个服务向另外一个服务发送请求
-
seo不友好
第一次请求的时候没有某些信息,响应体中没有包含某些内容,这些内容是通过ajax向服务器端发送请求获取来的。通过js动态创建到页面中的。
爬虫没办法爬到这些内容(ajax后期请求的内容)
1.5谷歌浏览器查看响应
举个登录的例子
查看请求,在我们发送请求的时候,浏览器会帮我们把http这个报文封装好,封装好之后将其发到目标服务器的指定端口
原始的请求体内容
请求报文看这两个部分
响应报文看这两个部分:
这里是关于请求参数的数据
1.6安装node
1.7express框架
因为我们需要给服务端发请求,这里我们需要一个服务端
npm init --yes
npm i express
编写启动代码
//1.引入express
const { application } = require('express');
const express = require('express');
//2.创建应用对象
const app = express();
//3.创建路由规则
// request是对请求报文的封装
// response是对响应报文的封装
app.get('/', (request, response) => {
response.send('Hello express');
});
//4.监听端口启动服务
app.listen(8840, () => {
console.log('服务已经启动,8840端口监听中...')
})
进入进行启动
PS E:\Ajax\代码\2express框架> node .\express基本使用.js
服务已经启动,8840端口监听中...
1.8原生ajax框架
1.8.1请求的基本操作
如果请求/server这个就会执行里面的代码
//1.引入express
const { application } = require('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 express');
});
//4.监听端口启动服务
app.listen(8840, () => {
console.log('服务已经启动,8840端口监听中...')
})
当我们在启动的时候会报错:我们把旁边的这几个给关闭就好了
这里占用的原因是:
打个比方,这里有一条小吃街,本来我8000号摊位我来卖煎饼果子,然后之后来了一个人要卖鸡蛋灌饼,他要么另外找一个地方(申请一个新的端口),或者让卖煎饼果子的离开(释放原来的8000号端口)。
我们把之前的终结,再次启动
这里就是对Ajax的请求进行筛选
在页面上显示从服务
<!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 #90b;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
</body>
<script>
//获取 button元素
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById('result')
//绑定事件
btn.onclick = function() {
//console.log('test');
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化 设置请求的方法和
// 第一个参数是发送什么类型的请求
// 第二个参数是给谁发
xhr.open('GET', 'http://127.0.0.1:8840/server');
//3.发送
xhr.send();
//4.事件绑定 处理服务端返回的结果
//on 相当于 when 当...的时候
// readystate 是 xhr对象中的属性,表示状态 0 1 2 3 4
//change 改变
xhr.onreadystatechange = function() {
//判断 (服务端反悔了所有的结果)
if (xhr.readyState == 4) {
//判断响应的状态码 200 404
//2xx成功
if (xhr.status >= 200 && xhr.status <= 300) {
//处理结果 行 头 空行 体
//1.响应行
// console.log(xhr.status); //状态码
// console.log(xhr.statusText); //状态字符串
// console.log(xhr.getAllResponseHeaders()); //所有的响应头
//设置result的文本
result.innerHTML = xhr.response
} else {
}
}
}
}
</script>
</html>
1.8.2设置请求参数
传入参数访问
<!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 #90b;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
</body>
<script>
//获取 button元素
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById('result')
//绑定事件
btn.onclick = function() {
//console.log('test');
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化 设置请求的方法和
// 第一个参数是发送什么类型的请求
// 第二个参数是给谁发
xhr.open('GET', 'http://127.0.0.1:8840/server?a = 100&b=200&c=300');
//3.发送
xhr.send();
//4.事件绑定 处理服务端返回的结果
//on 相当于 when 当...的时候
// readystate 是 xhr对象中的属性,表示状态 0 1 2 3 4
//change 改变
xhr.onreadystatechange = function() {
//判断 (服务端反悔了所有的结果)
if (xhr.readyState == 4) {
//判断响应的状态码 200 404
//2xx成功
if (xhr.status >= 200 && xhr.status <= 300) {
//处理结果 行 头 空行 体
//1.响应行
// console.log(xhr.status); //状态码
// console.log(xhr.statusText); //状态字符串
// console.log(xhr.getAllResponseHeaders()); //所有的响应头
//设置result的文本
result.innerHTML = xhr.response
} else {
}
}
}
}
</script>
</html>
1.8.3post请求
在刚才server.js中添加post
app.post('/server', (request, response) => {
//设置响应头
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应体
response.send('Hello express');
});
<!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></title>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #90b;
}
</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:8840/server');
//3.发送
xhr.send();
//4.事件绑定
xhr.onreadystatechange = function() {
//判断
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
//处理服务端返回的结果
result.innerHTML = xhr.response;
}
}
}
console.log("test");
});
</script>
</body>
</html>
请求体传入参数:
xhr.send('a=100&b=200&c=300');
请求体用什么格式都可以,只要能处理就行
1.8.4设置请求头信息
设置预定义的请求头:
//2.初始化 设置类型与URL
xhr.open('POST', 'http://127.0.0.1:8840/server');
//设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//3.发送
xhr.send('a=100&b=200&c=300');
设置自定义的请求头
xhr.setRequestHeader('name', 'sgc');
这里会警告,因为这是我们自己定义的请求头
我们可以在server.js中设置响应头
app.post('/server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//响应头
response.setHeader('Access-Control-Allow-Headers', '*')
//设置响应体
response.send('Hello express');
});
但是设置了之后我们还是不行,这里我们需要把post转换为all
app.all('/server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//响应头
response.setHeader('Access-Control-Allow-Headers', '*')
//设置响应体
response.send('Hello express');
});
可以接收任何类型的请求
1.8.5服务器端响应json数据
修改server.js的代码
app.all('/json-server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader(
// 设置响应头,设置允许跨域
'Access-Control-Allow-Origin', '*'
);
//响应头
response.setHeader('Access-Control-Allow-Headers', "*");
//响应一个数据
const data = {
name: 'atguigu'
};
//对对象进行字符串的转换
let str = JSON.stringify(data);
//设置响应体,只能接收字符串
response.send(str);
});
这里记得把之前的post请求先给注释掉
<!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></title>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #90b;
}
</style>
</head>
<body>
<div id="result"></div>
<script>
const result = document.getElementById("result");
// 键盘按下事件
window.onkeydown = function() {
const xhr = new XMLHttpRequest();
//设置响应体 数据类型
xhr.responseType = 'json';
xhr.open('GET', 'http://127.0.0.1:8840/json-server');
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// console.log(xhr.response);
// result.innerHTML = xhr.response;
//1.手动对数据进行转化
// let data = JSON.parse(xhr.response);
// console.log(data);
// 2.自动转换
console.log(xhr.response);
result.innerHTML = data.name;
}
}
}
}
</script>
</body>
</html>
设置自动转化:
//设置响应体 数据类型
xhr.responseType = 'json';
// 自动转换
console.log(xhr.response);
result.innerHTML = data.name;
1.9nodemon自动重启工具安装
输入
npm install -g nodemon
再次输入
nodemon .\server.js
1.10IE浏览器缓存问题
ie请求之后会把结果缓存起来,下一次再来获取的数据的时候并不是服务器里面最新的数据,而是浏览器中换粗的数据,对于时效性比较强的软件,ajax会影响显示。
加一个时间戳
xhr.open("GET", 'http://127.0.0.1:8840/ie?t=' + Date.now());
1.11超时问题
//延时响应
app.get('/delay', (request, response) => {
//设置响应头
response.setHeader('Access-Control-Allow-Origin', '*');
setTimeout(() => {
//设置响应体
response.send('延时响应')
}, 3000)
});
<script>
const btn = document.getElementsByTagName('button')[0];
const result = document.querySelector('#result');
btn.addEventListener('click', function() {
const xhr = new XMLHttpRequest();
//超时设置 2s
xhr.timeout = 2000;
//超时处理
xhr.ontimeout = function() {
alert("网络异常,请稍后重试!!");
}
xhr.open("GET", 'http://127.0.0.1:8840/delay');
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response;
}
}
}
})
</script>
还可以设置网络异常回调
//网络异常回调
xhr.onerror = function() {
alert("你的网络似乎除了一些问题");
}
取消发送请求:x.abort();
<body>
<button>点击发送</button>
<button>点击取消</button>
<div></div>
<script>
//获取元素对象
const btns = document.querySelectorAll('button');
btns[0].onclick = function() {
x = new XMLHttpRequest();
x.open('GET', 'http://127.0.0.1:8840/delay');
x.send();
}
//abort方法是属于ajax对象的
btns[1].onclick = function() {
x.abort();
}
</script>
</body>
<script>
1.12重复请求问题
<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:8840/delay');
x.send();
x.onreadystatechange = function() {
if (x.readyState === 4) {
//修改标识变量
isSending = false;
}
}
}
//abort方法是属于ajax对象的
btns[1].onclick = function() {
x.abort();
}
</script>
重复多次请求,但是每次只有一个正在请求中
第二章 jQuery中的ajax
2.1get
crossorigin*="anonymous"
向这个资源发送请求的时候将不会携带cookie
app.all('/json-server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader(
// 设置响应头,设置允许跨域
'Access-Control-Allow-Origin', '*'
);
//响应头
response.setHeader('Access-Control-Allow-Headers', "*");
//响应一个数据
const data = {
name: 'atguigu'
};
//对对象进行字符串的转换
let str = JSON.stringify(data);
//设置响应体,只能接收字符串
response.send(str);
});
//针对IE缓存
app.get('/ie', (request, response) => {
//设置响应头
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应体
response.send('IE缓存3');
});
//延时响应
app.all('/delay', (request, response) => {
//设置响应头
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
setTimeout(() => {
//设置响应体
response.send('延时响应')
}, 1000)
});
//JQuery服务
app.all('/jquery-server', (request, response) => {
//设置响应头
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
const data = { name: '尚硅谷' };
response.send(JSON.stringify(data));
});
//4.监听端口启动服务
app.listen(8840, () => {
console.log('服务已经启动,8840端口监听中...')
})
//JQuery服务
app.all('/jquery-server', (request, response) => {
//设置响应头
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
const data = { name: '尚硅谷' };
response.send(JSON.stringify(data));
});
<!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(url[, config])
axios.get('/axios-server', {
//url 参数
params: {
id: 100,
vip: 7
},
//请求头信息
headers: {
name: 'atguigu',
age: 20
}
}).then(value => {
console.log(value);
});
}
// POST 请求---axios.post(url[, data[, config]])
btns[1].onclick = function() {
axios.post('/axios-server', {
username: 'admin',
password: 'admin'
}, {
//url
params: {
id: 200,
vip: 9
},
//请求头参数
headers: {
height: 180,
weight: 180,
}
}).then(value => {
console.log(value);
});
}
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>