原生AJAX
AJAX 简介
- 全称为Asynchronous JavaScript And XML,即异步的 JS 和 XML
- 通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无需刷新即可获取数据
- AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式
AJAX 的特点
- 优点:① 可以无需刷新页面而与服务器端进行通信;② 允许根据用户事件来更新部分页面内容
- 缺点:① 没有浏览历史,不能回退;② 存在跨域问题(同源);③ SEO(搜索引擎优化)不友好
HTTP 协议
超文本传输协议,协议详细规定了浏览器和万维网服务器之间相互通信的规则
使用
Express的安装和使用
// 安装 npm install express
// 引入express
const express = require("express");
// 创建应用对象
const app = express();
// 创建路由规则:request请求报文 response响应报文
app.get("/server", function (request, response) {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", "*");
// 设置响应体
response.send("hello ajax get");
});
// 监听端口启动服务
app.listen(8000, function () {
console.log("服务已经启动,8000端口监听中...");
});
使用 Ajax 发送 GET 请求
<style>
#result {
width: 200px;
height: 100px;
border: 1px solid #000;
}
</style>
<button>点击发送请求</button>
<div id="result"></div>
<script>
$('button').on("click", function () {
// 创建对象
const xhr = new XMLHttpRequest();
// 初始化 设置请求的方法和URL ?后是设置的参数
xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
// 发送
xhr.send();
// 事件绑定 处理服务端返回的结果
/*
readyState 是xhr对象中的属性
0 未初始化
1 open方法调用完毕
2 send方法调用完毕
3 服务端返回了部分结果
4 服务端返回了所有结果
*/
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
// 判断响应状态码
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果 行 头 体
console.log(xhr.status, xhr.statusText); // 状态码 状态字符串
console.log(xhr.getAllResponseHeaders()); // 所有响应头
console.log(xhr.response); // 响应体
// 将响应内容写入div
$('#result').html(xhr.response);
}
}
};
})
</script>
使用 Ajax 发送 POST 请求
// all() 可以接收所有类型的请求
app.post("/server", function (request, response) {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", "*");
// response.setHeader("Access-Control-Allow-Headers", "*"); // 可以接收自定义的请求头信息
// 设置响应体
response.send("hello ajax post");
});
<style>
#result {
width: 200px;
height: 100px;
border: 1px solid #000;
}
</style>
<div id="result"></div>
<script>
$('#result').on("mouseenter", function () {
// 创建对象
const xhr = new XMLHttpRequest();
// 初始化 设置请求的方法和URL
xhr.open('POST', 'http://127.0.0.1:8000/server');
// 设置请求头 请求体内容的类型
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('name', 'dudu'); // 添加自定义头部信息会报错,需要在服务器进行配置
// 发送 请求体中可以写任何内容,只要服务端可以解析
xhr.send('a=100&b=200&c=300');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
// 判断响应状态码
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果 行 头 体
console.log(xhr.status, xhr.statusText); // 状态码 状态字符串
console.log(xhr.getAllResponseHeaders()); // 所有响应头
console.log(xhr.response); // 响应体
// 将响应内容写入div
$('#result').html(xhr.response);
}
}
};
})
</script>
服务端响应 json 数据
app.all("/json-server", function (request, response) {
// 设置响应头 设置允许跨域
response.setHeader("Access-Control-Allow-Origin", "*");
const data = {
name: "dudu",
age: 22,
};
// 设置响应体
response.send(JSON.stringify(data));
});
手动转换响应体数据
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send('a=100&b=200&c=300');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
// 判断响应状态码
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果 行 头 体
console.log(xhr.status, xhr.statusText); // 状态码 状态字符串
console.log(xhr.getAllResponseHeaders()); // 所有响应头
console.log(JSON.parse(xhr.response)); // 响应体
// 将响应内容写入div
$('#result').html(JSON.parse(xhr.response).name);
}
}
};
自动转换响应体数据
const xhr = new XMLHttpRequest();
// 设置响应体数据的类型 自动转换
xhr.responseType = 'json';
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send('a=100&b=200&c=300');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
// 判断响应状态码
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果 行 头 体
console.log(xhr.status, xhr.statusText); // 状态码 状态字符串
console.log(xhr.getAllResponseHeaders()); // 所有响应头
console.log(xhr.response); // 响应体
// 将响应内容写入div
$('#result').html(xhr.response.name);
}
}
};
nodemon 工具介绍
作用:可以自动重启node应用
安装:npm install -g nodemon
使用:使用nodemon server.js 来启动服务
IE缓存问题解决
- IE会对Ajax请求返回的响应体进行缓存,如果两次进行URL相同的请求,IE不会进行新的请求会返回缓存中的内容
- 解决:使用
xhr.open('GET', 'http://127.0.0.1:8000/server?t=' + Date.now());
进行访问,每次都是不同的URL
请求超时与网络异常
app.get("/server", function (request, response) {
response.setHeader("Access-Control-Allow-Origin", "*");
setTimeout(function () {
response.send("5s延时响应");
}, 5 * 1000);
});
const xhr = new XMLHttpRequest();
// 超时设置 如果2s内没有返回结果,请求就取消
xhr.timeout = 2 * 1000;
// 超时回调
xhr.ontimeout = function () {
alert('网络异常,请稍后重试');
};
// 网络异常
xhr.onerror = function () {
alert('你的网络似乎出了一些问题!');
}
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) {
$('#result').html(xhr.response);
}
}
};
手动取消请求
<button>点击发送</button>
<button>点击取消</button>
<script>
let xhr = null;
$('button').eq(0).on("click", function () {
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send();
});
$('button').eq(1).on("click", function () {
xhr = new XMLHttpRequest();
// 手动取消请求
xhr.abort();
});
</script>
重复发送请求的处理
let xhr = null;
// 标识是否正在发送Ajax请求
let isSending = false;
$('button').eq(0).on("click", function () {
if (isSending) {
xhr.abort();
}
xhr = new XMLHttpRequest();
isSending = true;
xhr.open('GET', 'http://127.0.0.1:8000/server');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
isSending = false;
}
};
});
jQuery 中的 Ajax
$.get('http://127.0.0.1:8000/jq-server', { a: 100, b: 200 }, function (data) {
console.log(data);
}, 'json');
$.post('http://127.0.0.1:8000/jq-server', { a: 100, b: 200 }, function (data) {
console.log(data);
});
$.ajax({
url: 'http://127.0.0.1:8000/jq-server',
data: { a: 100, b: 200 },
type: 'GET',
dataType: 'json',
success: function (data) {
console.log(data);
},
timeout: 2 * 1000,
error: function () {
console.log('出错啦');
},
headers: {
c: 300,
d: 400
}
});
Axios 发送 Ajax 请求
// 配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000';
$('button').eq(0).on("click", function () {
axios.get('/server', {
params: {
a: 100,
b: 200
},
headers: {
name: 'dudu',
age: 20
}
}).then(value => {
// 包括详细响应信息的对象
console.log(value);
});
});
$('button').eq(1).on("click", function () {
axios.post('/server',
// 请求体
{
name: 'dudu',
age: 20
},
{
params: {
a: 100,
b: 200
},
headers: {
name: 'dudu',
age: 20
},
}
);
});
$('button').eq(2).on("click", function () {
axios({
method: 'post',
url: '/server',
params: {
a: 100, b: 200
},
headers: {},
data: {}
});
});
fetch 方法发送 Ajax 请求
$("button").eq(0).on("click", function () {
fetch("http://127.0.0.1:8000/server?vip=10", {
method: "post",
headers: {
name: "dudu",
},
body: "username=admin&password=admin",
}).then((response) => {
// return response.text();
return response.json();
}).then((response) => {
console.log(response);
});
});
跨域
- 同源策略:协议、域名、端口号必须完全相同。违背同源策略就是跨域
- Ajax默认遵循同源策略
解决方式一:JSONP
- JSONP 是一个非官方的跨域解决方案,只支持 get 请求。
- 在网页中有一些标签天生具有跨域能力,比如:img link iframe script,JSONP就是利用 script 标签的跨域能力来发送请求的
用户名:<input type="text" id="username">
<p></p>
<script>
$("#username").on("blur", function () {
var name = this.value;
// 发送请求,检测用户名是否存在
var url = "http://127.0.0.1:8000/server";
var $request = $('<script src="' + url + '"><//script>');
$('body').append($request);
});
function handle(data) {
$("#username").css("border", "solid 1px red");
$('p').html(data.msg);
}
</script>
app.all("/server", function (request, response) {
response.setHeader("Access-Control-Allow-Origin", "*");
const data = {
exist: 1,
msg: "用户名已经存在",
};
// 设置响应体
response.end("handle(" + JSON.stringify(data) + ")");
});
jQuery 实现
<button>点击发送jsonp请求</button>
<p></p>
<script>
$("button").on("click", function () {
var url = "http://127.0.0.1:8000/server?callback=?";
$.getJSON(url, function (data) {
$('p').html("姓名:" + data.name + "<br/>年龄:" + data.age);
});
});
</script>
app.all("/server", function (request, response) {
response.setHeader("Access-Control-Allow-Origin", "*");
const data = {
name: "dudu",
age: 22,
};
let cb = request.query.callback;
// 设置响应体
response.end(cb + "(" + JSON.stringify(data) + ")");
});
解决方式二:CORS(跨域资源共享)
- 官方的跨域解决方案
- 不需要在客户端坐任何特殊的操作,完全在服务器中进行处理
- 支持get和post请求
- 通过设置一组响应头来完成配置,例如:
response.setHeader("Access-Control-Allow-Origin", "*");
,其他的请求头可以参考 https://developer.mozilla.org/zh-CN/docs/Glossary/CORS