Ajax使用
Ajax(Asynchronous JavaScript And XML)是浏览器提供的一套方法,可以实现页面无刷新更新数据,提高网站浏览体验
Ajax相关
Ajax不是新的编程语言,而是将现有的标准组合使用的方式
通过Ajax可以在浏览器中向服务器发送异步请求,无需刷新页面与服务端通信,获取数据,允许根据用户事件来更新部分页面内容
但是没有浏览历史,不能回退,且存在跨域问题,对SEO优化不好
XML 可扩展标记语言,用于传输和存储数据
与html格式类似,但html中都是预定义标签,而XML全是自定义标签,用于表示一些数据
现在已经被JSON取代
// XML格式
<Student>
<name>人</name>
<age>18</age>
<gender>男</gender>
</Student>
// JSON格式
{"name":"人","age":18,"gender":"男"}
http请求报文、响应报文的格式与参数
- 请求报文
请求行 1.请求方式 如 /GET 2.URL 3.http协议版本 HTTP/1.1
请求头 Host: www.baidu.com
Cookie: ...
Content-Type: ...
User-Agent: ...
....
空行
请求体 username=admin&password=123456
- 响应报文
响应行 1.http协议版本 HTTP/1.1 2.响应状态码 200 3.响应状态字符串
响应头 Content-Type: ... // 网页描述
Content-length: ...
Content-encodeing: ...
....
空行
响应体 <html> // 网页内容被放在响应体中
<head>
</head>
<body>
</body>
</html>
Chrome控制台查看通信报文
F12 -> NetWork/网络 加载网页所有的请求都会列在这里
点击请求弹出详情标签页,主要关注 Headers/标头 与 Response/响应
node.js基本使用,通过node简单搭建服务端
- 1.初始化环境:调出控制台集成终端(shift+command+Y),或在项目最外层根目录中右键 输入
npm init --yes
- 2.安装express框架
npm i express
- 3.新建并编写一个js文件作为服务端
- 4.集成终端输入
node js文件名
启动服务,按control+C
关闭服务- 当服务端代码修改时,需要重启服务
// 引入express
const express = require('express');
// 创建应用对象
const app = express();
// 创建路由规则
// 参数1 端口服务
// 回调函数参数 request 对请求报文的封装
// 回调函数参数 response 对响应报文的封装
// 对get请求的服务
app.get('/server', (request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 设置响应体
response.send('hello forGET');
});
// "http://127.0.0.1:8000/server"
// 当访问到此URL或接收到针对此服务的请求时,就会执行回调函数中的代码,并由response作出响应
// 监听端口启动服务
app.listen(8000, () => {
console.log('服务已在8000端口启动');
});
// 此时在"http://127.0.0.1:8000" + "/server"(get或post的第一个参数) 就可以访问到
// 或者"localhost:8000" + "/server" 访问
- nodemon安装
node服务端安装自动重启工具nodemon 当服务端发生改动时自动重启
集成终端输入npm install -g nodemon
mac系统需输入sudo npm install -g nodemon
安装完成后,集成终端输入nodemon js文件名
启动服务
Ajax使用
- 发送GET请求
<button>点击发送请求</button>
<div id="getResult"></div>
<script>
// 获取元素
const btn = document.getElementsByTagName('button')[0];
const getResult = document.getElementById('getResult');
// 点击事件
btn.onclick = function() {
// 使用Ajax 4个步骤
// 1.创建Ajax对象
const xhr = new XMLHttpRequest();
// 2.初始化 设置 请求方式 和 url
xhr.open('GET', 'http://127.0.0.1:8000/server');
// 3.发送请求
xhr.send();
// 4.事件绑定 处理服务端返回的结果 xhr.onreadystatechange
// readystate xhr对象属性,状态码 0,1,2,3,4
// 每当 readyState 发生改变时,都会执行函数
xhr.onreadystatechange = function() {
// 4代表服务端已返回所有的响应结果
if (xhr.readyState === 4) {
// 响应状态码中 以2开头的都是响应成功
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.status); // 响应状态码
console.log(xhr.statusText); // 响应状态字符串
console.log(xhr.getAllResponseHeaders()); // 所有响应头
console.log(xhr.response); // 响应体
getResult.innerHTML = xhr.response;
}
}
}
}
</script>
- 设置GET请求参数
// 在设置请求方式和url时,在url后添加"?"+参数,参数间以&连接
xhr.open('GET', 'http://127.0.0.1:8000/server?a=1&b=2&c=3');
- 发送POST请求
<div id="postResult"></div>
<script>
// 获取元素
const btn = document.getElementsByTagName('button')[0];
const postResult = document.getElementById('postResult');
// 鼠标事件
postResult.onmouseenter = function() {
// 1.创建Ajax对象
const xhr = new XMLHttpRequest();
// 2.初始化 设置 请求方式 和 url
xhr.open('POST', 'http://127.0.0.1:8000/server');
// 3.发送请求
xhr.send();
// 4.事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
postResult.innerHTML = xhr.response;
}
}
}
}
</script>
// 同时,在服务端需要有与之匹配的服务规则
// 对post请求的服务
app.post('/server', (request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
// 设置响应体
response.send('hello forPOST');
});
- 设置POST请求参数
// 发送请求时设置post请求参数
xhr.send('a=1&b=2&c=3');
xhr.send('a=1:b=2:c=3');
xhr.send('1234567');
// 参数格式灵活,但服务端一定要有与之相应的处理方式
- 设置请求头信息
// xhr.setRequestHeader() 方法 在发送请求前设置
xhr.setRequestHeader('Content','application/x-www-form-urlencoded'); // 预定义的请求头
xhr.setRequestHeader('name','abc'); // 自定义的请求头 一般会包含身份校验的信息,传递给服务器
// 自定义的请求头会报错,需要在服务端设置
// all可以接收任意类型的请求
app.all('/server', (request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 设置响应头
response.setHeader('Access-Control-Allow-Headers', '*');
// 设置响应体
response.send('hello forPOST');
});
服务端响应JSON数据
// 配置服务端
app.all('/json-server', (request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 设置响应头
response.setHeader('Access-Control-Allow-Headers', '*');
// 设置响应数据
const data = {
name: 'abc'
};
let str = JSON.stringify(data); // 传输的是字符串数据
// 设置响应体
response.send(str);
});
<div id="postResult"></div>
<script>
// 获取元素
const btn = document.getElementsByTagName('button')[0];
const postResult = document.getElementById('postResult');
// 鼠标事件
postResult.onmouseenter = function() {
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://127.0.0.1:8000/json-server');
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// postResult.innerHTML = xhr.response;
console.log(xhr.response);
// 处理数据 手动转换JSON数据
let data = JSON.parse(xhr.response);
console.log(data);
postResult.innerHTML = data.name;
}
}
}
}
</script>
// 自动转换JSON数据的方式
// 在发送请求前就设置响应体数据的类型
xhr.responseType = 'json';
异常问题解决
IE浏览器缓存问题
IE浏览器会对Ajax请求的数据做缓存,当下一次发送同样的请求时,会从缓存中取数据,而不是从服务器返回最新数据
// 在请求url后加上当前时间戳,IE浏览器会认为这是两次不同的请求
xhr.open('POST', 'http://127.0.0.1:8000/server?t=' +Date.now());
请求超时控制与网络异常处理
// 服务端配置延时3s响应
app.get('/delay', (request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 延时3s
setTimeout(() => {
// 设置响应体
response.send('hello forGET');
}, 3000);
});
<button>点击发送请求</button>
<div id="getResult"></div>
<script>
// 获取元素
const btn = document.getElementsByTagName('button')[0];
const getResult = document.getElementById('getResult');
// 点击事件
btn.onclick = function() {
const xhr = new XMLHttpRequest();
// 超时设置,2s后未收到响应,则取消请求
xhr.timeout = 2000;
// 超时回调
xhr.ontimeout = function() {
alert('网络异常,请稍后重试');
};
// 网络异常回调 // 模拟网络断开 F12控制台 No throttline改为Offline
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) {
getResult.innerHTML = xhr.response;
}
}
}
}
</script>
取消请求
// 服务端使用延时配置
// xhr.abort() 取消请求
<button>点击发送请求</button>
<button>点击取消请求</button>
<script>
// 获取元素
const btn = document.querySelectorAll('button');
// 放外面让两个元素都能访问到Ajax对象
let xhr = new XMLHttpRequest();
btn[0].onclick = function() {
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/delay');
xhr.send();
// 仅演示取消请求,数据不做处理
}
btn[1].onclick = function() {
xhr.abort();
}
</script>
请求重复发送问题
防止频繁发送相同请求,增加服务器负担
// 服务端使用延时配置
<button>点击发送请求</button>
<script>
// 获取元素
const btn = document.querySelectorAll('button');
// 放外面让两个元素都能访问到Ajax对象
let xhr = new XMLHttpRequest();
// 标识变量 记录发送状态
let isSending = false;
btn[0].onclick = function() {
if (isSending) xhr.abort(); // 如果正在发送,取消该请求,创建一个新的请求
xhr = new XMLHttpRequest();
// 修改标识变量 为正在发送
isSending = true;
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(xhr.response);
// 接收数据后,状态修改为未发送
isSending = false;
}
}
}
}
</script>
jQuery发送Ajax请求
-
jQuery文件 CDN链接
搜索bootcdn -> 查询jquery -> 复制粘贴<script>
标签链接 -
get请求
$.get(url,[data],[callback],[type]);
- post请求
$.post(url,[data],[callback],[type]);
- get与post请求 参数
- url:请求地址
- data:参数
- callback:载入成功的回调函数
- type:返回内容格式,XML、html、script、json、text、_default
- 通用请求方法ajax
$.ajax({ })
个性化参数更多 查看文档
// 服务端配置
app.all('/jquery-server', (request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 设置响应头
response.setHeader('Access-Control-Allow-Headers', '*');
const data = { name: 'abc' };
// 设置响应体
response.send(JSON.stringify(data));
});
<button>get</button>
<button>post</button>
<button>ajax</button>
<script>
$('button').eq(0).click(function() {
$.get('http://127.0.0.1:8000/jquery-server', {a: 100,b: 200}, function(data) {
console.log(data);
});
});
$('button').eq(1).click(function() {
$.post('http://127.0.0.1:8000/jquery-server', {a: 100,b: 200}, function(data) {
console.log(data);
}, 'json'); // 返回内容自动转换格式
});
$('button').eq(2).click(function() {
$.ajax({
url: 'http://127.0.0.1:8000/jquery-server', // 请求url
data: {a: 100,b: 200}, // 参数
type: 'GET', // 请求类型
dataType: 'json', // 响应体数据类型
// 请求成功回调函数
success: function(data) {
console.log(data);
},
timeout: 2000, // 超时时间
// 请求失败回调函数 超时或网络异常都会调用
error: function() {
console.log('请求失败');
},
// 自定义 头信息
headers: {c: 3,d: 4}
});
});
</script>
Ajax工具库 axios
使用npm下载或CDN链接 github
或者搜索bootcdn -> 查询axios -> 复制粘贴 <script>
标签链接
axios发送请求
// 服务端配置
app.all('/axios-server', (request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 设置响应头
response.setHeader('Access-Control-Allow-Headers', '*');
const data = { name: 'abc' };
// 设置响应体
response.send(JSON.stringify(data));
});
<button>get</button>
<button>post</button>
<button>axios函数</button>
<script>
const btn = document.querySelectorAll('button');
// 配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000';
btn[0].onclick = function() {
axios.get('/axios-server', {
// 请求参数
params: {
ID: 12345
},
// 自定义请求头参数
headers: {
name: 'abc'
}
}).then(value => { // 数据返回与处理
console.log(value);
})
};
btn[1].onclick = function() {
axios.post('/axios-server', {
username: 'admin', // 请求体
password: 'admin'
}, {
// 请求参数
params: {
ID: 123
},
// 自定义请求头参数
headers: {
age: 1
}
}).then(value => { // 数据返回与处理
console.log(value);
})
};
btn[2].onclick = function() {
// axios函数发送请求
axios({
method: 'POST',
url: '/axios-server',
// 请求参数
params: {
ID: 123
},
// 自定义请求头参数
headers: {
age: 1
},
// 请求体参数
data: {
username: 'admin',
password: 'admin'
}
}).then(response => { // 数据返回与处理
console.log(response);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.data);
})
};
</script>
fetch函数
// 服务端
app.all('/fetch-server', (request, response) => {
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 设置响应头
response.setHeader('Access-Control-Allow-Headers', '*');
const data = { name: 'abc' };
// 设置响应体
response.send(JSON.stringify(data));
});
<button>发送请求</button>
<script>
const btn = document.querySelector('button');
btn.onclick = function() {
fetch('http://127.0.0.1:8000/fetch-server', {
// 请求方式
method: 'POST',
// 请求头
headers: {
name: 'a'
},
// 请求体
body: 'username=admin&password=admin'
}).then(response => { // 响应数据处理
// return response.text();
return response.json();
}).then(response => {
console.log(response);
})
}
</script>
跨域
同源策略
是浏览器的一种安全策略,确保一个应用中的资源只能被本应用的资源访问
同源:网页请求的url与目标资源的url,协议、域名、端口,必须完全相同违背同源策略就是跨域
- 同源示例
// 服务端配置
// 引入express
const express = require('express');
// 创建应用对象
const app = express();
app.get('/page', (request, response) => {
// 响应一个页面
response.sendFile(__dirname + '/JSTest.html');
// 通过 http://127.0.0.1:8000/page 打开页面
});
app.get('/data', (request, response) => {
// 响应信息
response.send('userData');
// 只有通过http://127.0.0.1:8000/page打开的页面,与请求才是同源(相同url端口的服务)
// 使用live server插件打开的页面端口为5500,而5500端口没有此get服务
});
// 监听端口启动服务
app.listen(8000, () => {
console.log('服务已在8000端口启动');
});
<button>发送请求</button>
<script>
const btn = document.querySelector('button');
btn.onclick = function() {
const xhr = new XMLHttpRequest();
// 满足同源策略 url可以简写
// xhr.open('GET', 'http://127.0.0.1:8000/data');
xhr.open('GET', '/data');
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
}
}
}
}
</script>
JSONP跨域解决方案
JSONP (JSON with Padding),是非官方的跨域解决方案,只支持get请求
在网页有一些标签本身具有跨域能力,比如img、link、iframe、script
JSONP是利用script标签的跨域能力来发送请求
- 简单跨域示例
<div id="result"></div>
<script>
function handle(data) {
const result = document.getElementById('result');
result.innerHTML = data.name;
}
</script>
<!-- <script src="data.js"></script> -->
<!-- 使用live server插件开启5500端口服务,再通过文件打开页面,此时js文件引入路径与页面完全不同,但引入仍然有效-->
<script src="http://127.0.0.1:5500/data.js"></script>
// data.js文件
const data = {
name: 'nbname'
}
handle(data);
- 使用script跨域
// 服务端
// 引入express
const express = require('express');
// 创建应用对象
const app = express();
app.get('/check-username', (request, response) => {
const data = {
exist: 1,
msg: '用户名已存在'
}
let str = JSON.stringify(data);
// 返回一段js代码
response.end(`handle(${str})`);
});
// 监听端口启动服务
app.listen(8000, () => {
console.log('服务已在8000端口启动');
});
用户名:<input type="text" id="username">
<p></p>
<script>
const input = document.getElementById('username');
const p = document.querySelector('p');
// 修改表单元素样式
function handle(data) {
input.style.border = 'solid 1px #f00';
p.innerHTML = data.msg;
}
input.onblur = function() {
// 获取用户输入
let username = this.value;
// 向服务端发送请求,检测用户名是否存在
// 创建script标签
const script = document.createElement('script');
// 设置src属性
script.src = 'http://127.0.0.1:8000/check-username';
// 添加script标签
document.body.appendChild(script);
}
</script>
- jQuery发送JSONP跨域请求
// 引入express
const express = require('express');
// 创建应用对象
const app = express();
app.get('/jquery-jsonp-server', (request, response) => {
const data = {
name: 'qwer'
}
let str = JSON.stringify(data);
// 接收callback参数 jQuery36003954591679019166_1648313886731
let cb = request.query.callback;
// 返回一段js代码
response.end(`${cb}(${str})`);
});
// 监听端口启动服务
app.listen(8000, () => {
console.log('服务已在8000端口启动');
});
<button>点击发送请求</button>
<div id="result"></div>
<script>
$('button').eq(0).click(function() {
// url后添加参数 ?callback=? 固定写法,虽然是空参数,但在运行时是有值的 jQuery36003954591679019166_1648313886731
$.getJSON('http://127.0.0.1:8000/jquery-jsonp-server?callback=?', function(data) {
$('#result').html(`
名称:${data.name}
`)
})
})
</script>
CORS跨域解决方案
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)
不需要在客户端做任何特殊操作,完全在服务器中处理,支持 get 和 post 请求
通过设置一个响应头告知浏览器,请求允许跨域
// 设置允许跨域 * 通配,允许跨域访问所有站点,也可以设置指定url
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Headers', '*');
response.setHeader('Access-Control-Allow-Method', '*');
查看更多响应头信息 MDN文档
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现