一、简介
ajax用于向服务端发送异步请求,服务端返回结果。
其最大的特征就是在不刷新页面的情况下,更新页面内容。
例如:你向下滚动页面,滚到底刷新新内容,就是等你翻到底部的时候,再向服务端发送请求,然后把数据插入页面。
1、XML可扩展标记语言(以前ajax返回的数据都是XML格式的,不过现在都是JSON格式了)
XML被设计用于传输和存储数据的。
XML和HTML类似,不同的是HTML都是预定义标签(预定义标签就是标签被提前定义好的),而XML中没有预定义标签,全部都是自定义标签,用来表示一些数据的
2、ajax
(1)优点
可以无需刷新页面而与服务器端进行通信
允许你根据用户事件来更新部分页面内容
(2)缺点
没有浏览历史,不能回退
存在跨域问题
SEO不友好(因为是动态发送请求获取数据,所以对爬虫不是特别友好,爬不到数据)
3.HTTP协议
hypertext transport protocal 超文本传输协议。
详细规定了浏览器和万维网之间互相通信的规则。
请求报文与响应报文:http://t.csdn.cn/0jUI8
二、ajax使用
1、安装express框架:
因为你要向服务端发送请求,就要有服务端,这里选择使用express创建服务端。
npm init --yes
npm i express
会生成一个package.json文件
2、ajax的get请求的基本操作
配置并启动express服务器
启动express服务器: 使用 node 加文件名,如node ajaxStudy/text7.js
但由于每次修改text7.js文件的内容都要重新启动一次,所以在终端输入npm install -g nodemon
再输入 nodemon 文件名,以后每一次修改text7.js文件会自动重新启动
(1)配置服务器并发送get请求
//1.引入express
// const { response } = require('express');
// const { request } = require('express');
const express = require('express');
//2.创建应用对象
const app = express();
//3.创建路由规则
app.get('/server', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 设置响应体
response.send('HELLO Ajax');
});
//4.监听端口服务
app.listen(8000,()=>{
console.log("服务器已启动...");
})
ajax发送get请求
<style>
.result{
width: 200px;
height: 200px;
border: solid 5px #bfa;
}
</style>
<body>
<button>点击发送请求</button>
<div class="result"></div>
<script>
// 获取button元素
const btn = document.getElementsByTagName('button')[0];
//绑定事件
btn.onclick = function(){
//1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化 设置请求方法 和 url,即向url对应的地址发送什么样的请求
xhr.open('GET','http://127.0.0.1:8000/server');
//3.发送
xhr.send();
// 4.事件绑定 处理服务端返回的结果
// on 当...的时候
//readystate 是xhr对象中的属性,表示状态0(表示初始状态) 1(表示open方法已经调用完毕) 2(表示send方法已经调用完毕) 3(表示服务端已经返回部分结果) 4(表示服务端返回了所有的结果)
//change 改变
// 这个方法改一次触发一次
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){//结果为true,表示返回了所有结果
// 判断响应状态码 200 404 403 401 500,2开头的数字都表示成功
if(xhr.status >=200 && xhr.status<300){
// 处理结果
console.log(xhr.status);//状态码
console.log(xhr.statusText);//状态字符串
console.log(xhr.getAllResponseHeaders);//所有响应头
console.log(xhr.response);//响应体
}else{
}
}
}
}
</script>
</body>
</html>
(2)、配置服务器并发送post请求
//1.引入express
// const { response } = require('express');
// const { request } = require('express');
const express = require('express');
//2.创建应用对象
const app = express();
//3.创建路由规则
//get规则
app.get('/server', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 设置响应体
response.send('HELLO Ajax GET');
});
//post规则
app.all('/server', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//响应头
response.setHeader('Access-Control-Allow-Headers','*');
// 设置响应体
response.send('HELLO Ajax POST');
});
//4.监听端口服务
app.listen(8000,()=>{
console.log("服务器已启动...");
})
<style>
#result{
width: 200px;
height: 200px;
border: solid 5px #bfa;
}
</style>
<body>
<button>点击发送post请求</button>
<div id="result"></div>
<script>
// 获取button元素
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById("result");
//绑定事件
btn.onclick = function(){
//1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化 设置请求方法 和 url,即向url对应的地址发送什么样的请求
xhr.open('POST','http://127.0.0.1:8000/server');
/**
* 设置请求头,可以自定义请求头,需要在创建路由规则时将app.post改为app.all并且设置response.setHeader('Access-Control-Allow-Headers','*');
*/
xhr.setRequestHeader('name','axiba');
//3.发送
/**
* 设置请求体的方式:
* xhr.send('a=10&b=20');xhr.send('a:10&b:20');xhr.send('5934hf938ut2');
*/
xhr.send();
// 4.事件绑定 处理服务端返回的结果
// on 当...的时候
//readystate 是xhr对象中的属性,表示状态0(表示初始状态) 1(表示open方法已经调用完毕) 2(表示send方法已经调用完毕) 3(表示服务端已经返回部分结果) 4(表示服务端返回了所有的结果)
//change 改变
// 这个方法改一次触发一次
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){//结果为true,表示返回了所有结果
// 判断响应状态码 200 404 403 401 500,2开头的数字都表示成功
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>
</body>
(3)、服务端返回字符串,我要转成JSON数据
<style>
#result{
width: 200px;
height: 200px;
border: solid 5px #bfa;
}
</style>
<body>
<button>JSON</button>
<div id="result"></div>
<script>
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById("result");
btn.onclick = function(){
// console.log("----");
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){
// console.log("--JSON--");
// result.innerHTML = xhr.response;
// 再将接收到的字符串手动转换成对象
// let data = JSON.parse(xhr.response);
// console.log(data);
// result.innerHTML = data.name;
// console.log(typeof(xhr.response));
//自动转换,需要在上面设置xhr.responseType = 'json';
console.log(xhr.response);
result.innerHTML = xhr.response.name;
}
}
}
}
</script>
</body>
//1.引入express
// const { response } = require('express');
// const { request } = require('express');
const express = require('express');
//2.创建应用对象
const app = express();
//3.创建路由规则
//get规则
app.get('/server', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 设置响应体
response.send('HELLO Ajax GET');
});
//post规则
app.all('/server', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//响应头
response.setHeader('Access-Control-Allow-Headers','*');
// 设置响应体
response.send('HELLO Ajax POST');
});
//用JSON的方法将对象转换成字符串
app.all('/json-server', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//响应头
response.setHeader('Access-Control-Allow-Headers','*');
// 设置一个对象数据
const data = {
name:'atguigu'
};
// 将data对象转换成字符串
let str = JSON.stringify(data);
// 设置响应体,发送字符串
response.send(str);
});
//4.监听端口服务
app.listen(8000,()=>{
console.log("服务器已启动...");
})
(4)、IE缓存问题:(ie已经g了)
IE浏览器会对ajax请求结果进行缓存,下一次请求时,ie浏览器会用缓存的数据,而服务端修改返回的数据后,无法显示修改的数据,所以对于时效性较强的数据就不能正常显示。
解决方法:
//在初始化的时候
xhr.open('POST','http://127.0.0.1:8000/ie?t='+Date.now());
//原理是传递数据的不变的就会使用原来的缓存的,而加上一个时间戳(因为生成的时间戳是不一样的)传递的数据就会变化,ie会重新获得服务端的值
(5)、ajax请求超时与网络异常处理
<style>
#result{
width: 200px;
height: 200px;
border: solid 5px #bfa;
}
</style>
<body>
<button>JSON</button>
<div id="result"></div>
<script>
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById("result");
btn.onclick = function(){
// console.log("----");
const xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/delay');
//2s超时设置
xhr.timeout = 2000;
xhr.ontimeout = function(){
alert("你的网络似乎除了一些问题!");
}
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status >= 200 && xhr.status < 300){
// console.log("--JSON--");
// result.innerHTML = xhr.response;
result.innerHTML = xhr.response;
}
}
}
}
</script>
</body>
//1.引入express
// const { response } = require('express');
// const { request } = require('express');
const express = require('express');
//2.创建应用对象
const app = express();
//3.创建路由规则
//get规则
app.get('/server', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 设置响应体
response.send('HELLO Ajax GET');
});
//post规则
app.all('/server', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//响应头
response.setHeader('Access-Control-Allow-Headers','*');
// 设置响应体
response.send('HELLO Ajax POST');
});
//用JSON的方法将对象转换成字符串
app.all('/json-server', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//响应头
response.setHeader('Access-Control-Allow-Headers','*');
// 设置一个对象数据
const data = {
name:'atguigu'
};
// 将data对象转换成字符串
let str = JSON.stringify(data);
// 设置响应体,发送字符串
response.send(str);
});
app.get('/delay', (request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 设置延时响应
setTimeout( ()=>{
//设置响应体
response.send('延时响应');
},3000);
});
//4.监听端口服务
app.listen(8000,()=>{
console.log("服务器已启动...");
})
(6)、手动处理请求
<style>
#result{
width: 200px;
height: 200px;
border: solid 5px #bfa;
}
</style>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<button>点击取消请求</button>
<script>
const btn1 = document.getElementsByTagName('button')[0];
const result = document.getElementById("result");
const btn2 = document.getElementsByTagName('button')[1];
var xhr = null;
btn1.onclick = function(){
// console.log("----");
xhr = new XMLHttpRequest();
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){
// console.log("--JSON--");
// result.innerHTML = xhr.response;
result.innerHTML = xhr.response;
}
}
}
}
btn2.onclick = function(){
xhr.abort();
}
</script>
</body>
(7)、对于重复发送ajax请求问题,可以做一个判断
<style>
#result{
width: 200px;
height: 200px;
border: solid 5px #bfa;
}
</style>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<button>点击取消请求</button>
<script>
const btn1 = document.getElementsByTagName('button')[0];
const result = document.getElementById("result");
const btn2 = document.getElementsByTagName('button')[1];
var isSending = false;
var xhr = null;
btn1.onclick = function(){
// console.log("----");
//判断是否正在发送请求,如果正在发,取消当前发送的请求
if (isSending) xhr.abort();
xhr = new XMLHttpRequest();
//修改表示变量为true
isSending =true;
xhr.open('GET','http://127.0.0.1:8000/delay');
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
//发送完成修改表示变量为false
isSending = false;
if(xhr.status >= 200 && xhr.status < 300){
result.innerHTML = xhr.response;
}
}
}
}
btn2.onclick = function(){
xhr.abort();
}
</script>
</body>
请求体只有post请求才可以发送。
(8)、同源策略
同源:协议、域名、端口号完全相同。
跨域:违背同源策略就是跨域。
如何解决跨域:
1、JSONP是一个非官方的跨域解决方案,是纯粹凭借程序有的聪明才智开发出来的,只支持get请求。
网页中有些标签天生就具有跨域能力,比如:img link iframe script 。
JSONP就是利script标签的跨域能力来发送请求的。
//1.引入express
// const { response } = require('express');
// const { request } = require('express');
const { request, response } = require('express');
const express = require('express');
//2.创建应用对象
const app = express();
//3.创建路由规则
// jsonp服务
app.all('/jsonp-server',(request,response)=>{
response.send('hello jsonp-server----')
})
//4.监听端口服务
app.listen(8000,()=>{
console.log("服务器已启动...");
})
使用script标签发请求
<!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>
</head>
<body>
<!-- <script src="./server.js"></script> -->
<!-- 先用上面的方式引入,然后在浏览器检查-网络-右键server.js在新标签页中打开 -->
<!-- 这样src就能以网页地址的形式引入文件了 -->
<!-- <script src="http://127.0.0.1:5500/ajaxStudy/jsonp%E5%A4%84%E7%90%86%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98/server.js"></script> -->
<!-- 通过上面的形式,我们可以在src写服务端的地址,这样就能获取服务端的数据了 -->
<!-- src里面写服务器的地址,这样可以获得服务器返回的数据 -->
<script src="http://127.0.0.1:8000/jsonp-server"></script>
</body>
</html>
2.CORS官方的解决跨域的方案,完全在服务器中进行处理,不需要客户端做任何操作。
支持get和post请求。
通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器受到后就会对响应放行。
//在服务端配置一些响应头即可,上面的例子能够发送请求收到数据都是因为配置了这个响应头。
//第二个参数*表示所有端口都能够发送请求。可以设置为http://127.0.0.1.5500就只允许这个端口发送请求。
response.setHeader('Access-Control-Allow-Origin','*');
有一组响应头可以用来设置。这里只是讲了一种