AJAX简介
AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。就是异步的JS和XML。通过AJAX可以在浏览器像服务器发送异步请求。
AJAX优点
- 可以无需刷新页面与服务器端进行通信。页面请求数据的时候不需要刷新页面就能拿到想要的数据。
- 允许你根据用户事件来更新部分页面内容
AJAX缺点
- 没有浏览历史
- 存在跨域问题(同源)
- SEO不友好
AJAX的使用
HTTP
HTTP协议:协议详细规定了浏览器和万维网服务器之间相互通信的规则。 协议就是一种约定、一种规则。
HTTP主要是约定了两块的内容,一块是请求,一块响应。
请求
浏览器向服务端发送的内容称之为请求报文。请求行和头看Request Headers、请求体from Data。如果请求是一个GET请求那么Query String Parameters会对请求的URL内容做一个解析 重点格式与参数
- 请求行
请求行包括三部分 :请求类型(GET,POST)、URL路径、HTTP版本
- 请求头
请求头:名字冒号空格加值。
- 空行
空行是空的但是必须有。
- 请求体
如果是GET请求,请求体是空的,POST请求,请求体可以不为空。
响应
服务器给客户端返回的结果称之为响应报文。响应头Response Headers、响应体Response
- 响应行
响应行包括三部分 :协议版本、响应状态码、响应状态字符串。
- 响应头
响应头:名字冒号空格加值。
- 空行
空行是空的但是必须有。
- 响应体
主要的返回结果。里面是HTML内容。
XML简介
XML:可扩展标记语言。(HTML:超文本标记语言)它们都是由标签组成的。但是XML它是被设计用来传输和储存数据的,不同的是HTML中都是定义标签,而XML中没有定义标签,全都是自定义标签,用来表示一些数据。
使用AJAX发送GET请求
1.安装node.js
2.安装npm init --yes
3.安装npm i express
4.启动 node server.js (server.js
是文件名)
创建server.js
// 1、引入express
const express = require('express');
//2、创建应用对象
const app=express();
// 3、创建路由规则
// require请求报文的封装
// response响应报文的封装
app.get('/server',(require,response)=>{
// 设置响应头
response.setHeader('Access-Control-Allow-Origin','*'); //设置允许跨域
// 设置响应
response.send("hello AJAX");
})
// 4. 监听端口启动服务
app.listen(8000,()=>{
console.log("服务已经启动,8000,端口监听中...")
})
HTML页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
#result{
width: 200px;
height: 100px;
border: solid #ccc 1px;
}
</style>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
// 获取button元素
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById("result")
// 绑定事件
btn.onclick=function(){
// 创建对象
const xhr = new XMLHttpRequest();
// 初始化, 设置请求的方法和URL
// 设置URL参数
xhr.open("GET","http://127.0.0.1:8000/server?a=100&b=200&c=300");
// 发送
xhr.send();
// 事件绑定 作用是处理服务端返回来的结果
// on 相当于when 当...时候
// readystate 是xhr中的属性,有五个表示状态 0 1 2 3 4
// 1表示open方法调用完毕 2表示send方法调用完毕 3表示服务端返回的部分结果 4表示服务端返回的所有结果
// change本身是改变的意思,当改变的时候触发
xhr.onreadystatechange=function(){
// 判断当服务端返回所有的结果
if(xhr.readyState===4){
// 判断响应的状态 比如200 404 403 500
// 响应状态码中2开头的都是响应成功
if(xhr.status>=200 && xhr.status<300){
// 响应成功就处理结果
// 处理结果包括四部分 行 头 空行 体
// 1、响应行
// 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>
GET请求URL参数是直接在URL上拼接,但是在post请求的时候,参数在send()中设置
使用AJAX发送post请求
server.js
// 1、引入express
const express = require('express');
//2、创建应用对象
const app=express();
// 3、创建路由规则
// require请求报文的封装
// response响应报文的封装
app.get('/server',(require,response)=>{
// 设置响应头
response.setHeader('Access-Control-Allow-Origin','*'); //设置允许跨域
// 设置响应
response.send("hello AJAX");
});
//对应的post标识
app.post('/server',(require,response)=>{
// 设置响应头
response.setHeader('Access-Control-Allow-Origin','*'); //设置允许跨域
// 设置响应
response.send("hello AJAX");
});
// 4. 监听端口启动服务
app.listen(8000,()=>{
console.log("服务已经启动,8000,端口监听中...")
})
HTML页面
<!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>
</head>
<style>
#result{
width: 200px;
height: 100px;
border: tan solid 1px;
}
</style>
<body>
<p > 实现需求,当我鼠标放到div里面,请求的数据放在我的div里面</p>
<div id="result"></div>
<script>
//获取元素
const result = document.getElementById("result");
// 绑定事件
result.addEventListener("mouseover",function(){
// 创建对象
const xhr= new XMLHttpRequest();
// 初始化 设置请求类型和URL
xhr.open("POST","http://127.0.0.1:8000/server");
// 发送
// xhr.send("a=100&b=200&c=300"); //post中发送请求的参数
// 等同于
xhr.send("a:100&b:200&c:300"); //post中发送请求的参数
// 事件绑定
xhr.onreadystatechange=function(){
// 判断服务端响应回来的结果
if(xhr.readyState===4){
// 判断响应状态 2开头的都是成功的
if(xhr.status>=200 && xhr.status<300){
// 请求成功就处理服务端返回的结果
result.innerHTML=xhr.response;
}else{
}
}
}
})
</script>
</body>
</html>
设置请求头信息 setRequestHeader
Content-Type
设置请求体里面的类型的。application/x-www-form-urlencoded
请求体参数查询字符串。
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
设置信息我们不光可以设置预定义的,也可以自定义
xhr.setRequestHeader('name','atxiaocai')
自定义过后会报错,这个时候我们需要在服务端的JS里面server.js
设置一下
表示所有类型的头信息我都可以接受
response.setHeader('Access-Control-Allow-Headers','*');
这个时候还是会报错但是把server.js
代码中post
请求的标识换成all
就不会出现报错了
all表示可以接收任意类型的请求
app.all('/server',(require,response)=>{
// 设置响应头
response.setHeader('Access-Control-Allow-Origin','*'); //设置允许跨域
response.setHeader('Access-Control-Allow-Headers','*'); //表示所有类型的头信息我都可以接受
// 设置响应
response.send("hello AJAX");
});
AJAX--服务端响应JSON数据响应
server.js
// 1、引入express
const express = require('express');
//2、创建应用对象
const app=express();
// 3、创建路由规则
// require请求报文的封装
// response响应报文的封装
app.get('/server',(require,response)=>{
// 设置响应头
response.setHeader('Access-Control-Allow-Origin','*'); //设置允许跨域
// 设置响应
response.send("hello AJAX");
});
app.all('/server',(require,response)=>{
// 设置响应头
response.setHeader('Access-Control-Allow-Origin','*'); //设置允许跨域
response.setHeader('Access-Control-Allow-Headers','*'); //表示所有类型的头信息我都可以接受
// 设置响应
response.send("hello AJAX");
});
app.all('/json-server',(require,response)=>{
// 设置响应头
response.setHeader('Access-Control-Allow-Origin','*'); //设置允许跨域
response.setHeader('Access-Control-Allow-Headers','*'); //表示所有类型的头信息我都可以接受
// 响应一个数据
const data={
name:"小太阳"
}
// 对对象进行字符串转换
let str=JSON.stringify(data)
// 设置响应
response.send(str); //send里面只能放字符串
});
// 4. 监听端口启动服务
app.listen(8000,()=>{
console.log("服务已经启动,8000,端口监听中...")
})
HTML页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AJAX JSON</title>
</head>
<style>
#result {
width: 200px;
height: 100px;
border: tan solid 1px;
}
</style>
<body>
<p> 实现需求,在窗口下面按下键盘按钮,请求数据</p>
<div id="result"></div>
<script>
// 获取div
const result=document.getElementById("result")
// 绑定键盘按下事件
window.onkeydown=function(){
// 向服务端发送请求
const xhr=new XMLHttpRequest();
// 自动数据转换,借助xhr里面responseType
xhr.responseType="json"
// 调用open方法做一个初始化
xhr.open("GET","http://127.0.0.1:8000/json-server")
// 发送请求
xhr.send();
// 事件绑定
xhr.onreadystatechange=function(){
// 判断状态
if(xhr.readyState===4){
// 判断状态码是不是大于等于200小于300
if(xhr.status>=200 && xhr.status<300){
// console.log(xhr.response);
// result.innerHTML=xhr.response;
// 手动数据转换
// let data=JSON.parse(xhr.response);
// result.innerHTML=data.name
// 自动数据转换,借助xhr里面responseType
result.innerHTML=xhr.response.name
}
}
}
}
</script>
</body>
</html>
如果是一个对象应该怎么取到值
// 响应一个数据
const data={
name:"小太阳"
}
// 对对象进行字符串转换
let str=JSON.stringify(data)
// 设置响应
response.send(str); //send里面只能放字符串
// 手动数据转换
let data=JSON.parse(xhr.response);
result.innerHTML=data.name
// 自动数据转换,借助xhr里面responseType
xhr.responseType="json"; //写在向服务器发送请求过后
// 自动数据转换。
result.innerHTML=xhr.response.name
AJAX ---IE缓存问题
什么是IE缓存问题,IE浏览器会对AJAX请求的结果做一个缓存,这样就会导致下一次去请求的时候,这个时候走的是本地的缓存,并不是服务器返回的最新数据,这样就会影响结果。
AJAX---IE缓存解决方法,给请求URL加上一个时间戳?t="+Date.now()
,这样每次发送请求的时候URL就会不一样,这样就会重新去发新的请求而不是走本地缓存
xhr.open("GET","http://127.0.0.1:8000/ie?t="+Date.now());
AJAX请求超时与网络异常处理
我们不能保证服务端永远及时快速的响应,这个时候我们可以对AJAX做一个超时的设置,在请求超时和网络异常的情况下给用户提醒。
HTML页面
const btn = document.getElementsByTagName("button")[0];
const result = document.querySelector("#result");
btn.addEventListener("click", function () {
const xhr = new XMLHttpRequest();
// 超时设置 如果2秒之内还没有请求回来结果 就取消请求
xhr.timeout=2000;
// 超时回调
xhr.ontimeout=function(){
alert("数据请求超时")
}
xhr.onerror=function(){
alert("你的网络不佳,请检查网络")
}
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) {
result.innerHTML = xhr.response;
}
}
}
})
server.js页面
// 延时的服务
app.all('/delay',(require,response)=>{
// 设置响应头
response.setHeader('Access-Control-Allow-Origin','*'); //设置允许跨域
response.setHeader('Access-Control-Allow-Headers','*'); //表示所有类型的头信息我都可以接受
// 设置响应
setTimeout(()=>{
response.send("延迟响应");
},3000) //设置时间为3秒
});
AJAX取消请求
在发送请求过后,返回结果之前,手动取消请求。
只要调用abort
方法就能手动取消
<button>发送请求</button>
<button>取消请求</button>
<script>
const btns=document.querySelectorAll("button")
let xhr=null //此处使用let const的值不能够被修改
btns[0].onclick=function(){
const xhr=new XMLHttpRequest();
xhr.open("GET","http://127.0.0.1:8000/delay");
xhr.send();
}
btns[1].onclick=function(){
xhr.abort() //此处的xhr不在一个函数内,所以要在上面声明一下
}
</script>
AJAX重复发送请求的问题
在向服务器发送请求的时候,如果重复性发送同一个请求,就会给服务器造成压力。
在向服务器发送请求的时候,看一下有没有相同的请求,如果有那就把之前的请求取消掉,然后发送新的请求。
新增代码改动
let isSending = false; //是否正在发送AJAX请求
// 判断标识变量
// 如果正在发送请求,则取消该请求创建一个新的请求
if (isSending) xhr.abort();
// 修改标识码的值
isSending = true; //正在发送AJAX请求
xhr.onreadystatechange = function () {
// 判断请求是否完成
if (xhr.readyState === 4) { //状态为4就请求完成
// 修改标识变量
isSending = false;
}
}
整体代码
const btns = document.querySelectorAll("button")
let xhr = null; //此处使用let const的值不能够被修改
let isSending = false; //是否正在发送AJAX请求
btns[0].onclick = function () {
// 判断标识变量
// 如果正在发送请求,则取消该请求创建一个新的请求
if (isSending) xhr.abort();
xhr = new XMLHttpRequest();
// 修改标识码的值
isSending = true; //正在发送AJAX请求
xhr.open("GET", "http://127.0.0.1:8000/delay");
xhr.send();
// 在请求完成之后就应该还原成false
xhr.onreadystatechange = function () {
// 判断请求是否完成
if (xhr.readyState === 4) { //状态为4就请求完成
// 修改标识变量
isSending = false;
}
}
}