本文以 "快递配送" 类比 AJAX 通信机制,系统讲解原生 AJAX、jQuery AJAX、Fetch API 与 Axios 的使用方法,帮助零基础开发者彻底掌握异步数据交互核心技能。
一、为什么需要 AJAX?从 "快递配送" 说起
1.1 传统网页的痛点
想象你在餐厅吃饭:
- 同步模式:点完菜后必须等服务员把菜端上来,才能继续做其他事
- 异步模式:点完菜后不用等待,可继续喝茶聊天,服务员会在菜做好时通知你
在网页中:
<!-- 传统同步页面 -->
<form action="/submit" method="POST">
<input type="text" name="username">
<button type="submit">提交</button>
</form>
<!-- 提交后整个页面刷新 -->
这种模式在处理表单提交、数据加载时会导致页面闪烁、用户体验差。
1.2 AJAX 的工作原理
AJAX(Asynchronous JavaScript and XML)允许在不刷新整个页面的情况下,与服务器进行异步通信并更新部分网页。
// 原生AJAX示例
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/data', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
document.getElementById('result').innerHTML = xhr.responseText;
}
};
xhr.send();
执行顺序:
- 创建 XMLHttpRequest 对象
- 打开一个请求(指定 URL 和请求方法)
- 设置回调函数,监听状态变化
- 发送请求
- 服务器处理请求并返回数据
- 回调函数根据返回状态更新页面
1.3 AJAX 的应用场景
场景 | 示例 | 异步必要性 |
---|---|---|
表单提交 | 注册登录、评论发布 | 无需刷新页面,提升用户体验 |
数据加载 | 分页、无限滚动 | 减少页面加载时间,提高性能 |
实时更新 | 聊天消息、股票行情 | 动态更新数据,无需用户操作 |
数据验证 | 用户名查重、表单验证 | 即时反馈,提升用户体验 |
二、AJAX 核心技术详解
2.1 原生 AJAX:XMLHttpRequest 对象
2.1.1 基本用法
// 完整的原生AJAX请求
const xhr = new XMLHttpRequest();
// 监听状态变化
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // 请求完成
if (xhr.status === 200) { // 请求成功
console.log('响应数据:', xhr.responseText);
} else {
console.error('请求失败:', xhr.status);
}
}
};
// 打开请求
xhr.open('GET', 'https://api.example.com/data', true);
// 设置请求头(可选)
xhr.setRequestHeader('Content-Type', 'application/json');
// 发送请求
xhr.send();
2.1.2 处理不同类型的响应
// JSON响应处理
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText); // 解析JSON
console.log(data);
}
};
// 二进制响应处理
xhr.responseType = 'blob';
xhr.onload = function() {
const blob = xhr.response;
// 处理二进制数据
};
2.2 jQuery AJAX:简化异步请求
2.2.1 $.ajax () 方法
$.ajax({
url: 'https://api.example.com/data',
method: 'GET',
dataType: 'json',
success: function(data) {
console.log('成功:', data);
},
error: function(error) {
console.error('失败:', error);
}
});
2.2.2 快捷方法
// GET请求
$.get('https://api.example.com/data', function(data) {
console.log(data);
});
// POST请求
$.post('https://api.example.com/submit', { name: 'John' }, function(data) {
console.log(data);
});
2.3 Fetch API:现代的 AJAX 替代方案
2.3.1 基本用法
fetch('https://api.example.com/data')
.then(response => response.json()) // 解析JSON
.then(data => console.log(data))
.catch(error => console.error('错误:', error));
2.3.2 发送数据
// POST请求
fetch('https://api.example.com/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John' })
})
.then(response => response.json())
.then(data => console.log(data));
2.4 Axios:基于 Promise 的 HTTP 客户端
2.4.1 基本用法
// GET请求
axios.get('https://api.example.com/data')
.then(response => console.log(response.data))
.catch(error => console.error(error));
// POST请求
axios.post('https://api.example.com/submit', { name: 'John' })
.then(response => console.log(response.data))
.catch(error => console.error(error));
2.4.2 全局配置
// 设置默认配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = 'Bearer token';
// 发送请求
axios.get('/data')
.then(response => console.log(response.data));
三、实战案例:从表单提交到图片上传
3.1 案例一:表单异步提交
<!DOCTYPE html>
<html>
<head>
<title>AJAX表单提交</title>
</head>
<body>
<form id="myForm">
<input type="text" name="username" placeholder="用户名">
<input type="password" name="password" placeholder="密码">
<button type="submit">登录</button>
</form>
<div id="result"></div>
<script>
document.getElementById('myForm').addEventListener('submit', function(e) {
e.preventDefault(); // 阻止表单默认提交
const formData = new FormData(this);
// 使用Fetch API发送表单数据
fetch('/api/login', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
document.getElementById('result').innerHTML = data.message;
})
.catch(error => {
document.getElementById('result').innerHTML = '登录失败';
});
});
</script>
</body>
</html>
👉 效果示意图:
3.2 案例二:数据分页加载
// 分页加载数据
let currentPage = 1;
const loadMoreBtn = document.getElementById('loadMore');
loadMoreBtn.addEventListener('click', function() {
currentPage++;
loadData(currentPage);
});
function loadData(page) {
axios.get(`/api/posts?page=${page}`)
.then(response => {
const posts = response.data;
renderPosts(posts);
})
.catch(error => {
console.error('加载失败:', error);
});
}
3.3 案例三:图片上传预览
// 图片上传预览
const fileInput = document.getElementById('fileInput');
const preview = document.getElementById('preview');
fileInput.addEventListener('change', function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
preview.src = e.target.result;
}
reader.readAsDataURL(file);
// 上传图片
uploadImage(file);
}
});
function uploadImage(file) {
const formData = new FormData();
formData.append('image', file);
axios.post('/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
console.log('上传成功:', response.data);
})
.catch(error => {
console.error('上传失败:', error);
});
}
四、AJAX 常见错误与解决方案
4.1 跨域请求问题
错误信息:
Access to XMLHttpRequest at 'https://api.other.com' from origin 'http://localhost' has been blocked by CORS policy
解决方案:
- 在服务器端设置 CORS 头:
// Node.js示例
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
- 使用 JSONP(仅适用于 GET 请求)
- 使用代理服务器
4.2 错误处理
// 统一错误处理
axios.interceptors.response.use(
response => response,
error => {
if (error.response) {
// 请求已发送,服务器返回状态码非200
console.log('状态码:', error.response.status);
console.log('数据:', error.response.data);
console.log('请求头:', error.response.headers);
} else if (error.request) {
// 请求已发送,但没有收到响应
console.log('请求未响应:', error.request);
} else {
// 请求设置时出错
console.log('错误信息:', error.message);
}
return Promise.reject(error);
}
);
五、AJAX 面试高频问题
-
什么是 AJAX?它的优缺点是什么?
- AJAX 是异步的 JavaScript 和 XML,允许在不刷新整个页面的情况下与服务器进行异步通信
- 优点:提升用户体验、减少页面加载时间
- 缺点:SEO 不友好、可能导致过多的 HTTP 请求
-
AJAX 请求有哪些步骤?
- 创建 XMLHttpRequest 对象
- 打开请求
- 设置请求头
- 发送请求
- 监听状态变化
- 处理响应
-
GET 和 POST 请求的区别?
- GET 请求将参数附加在 URL 后面,POST 请求将参数放在请求体中
- GET 请求有长度限制,POST 请求没有
- GET 请求比 POST 请求更不安全
- GET 请求通常用于获取数据,POST 请求通常用于提交数据
六、技术笔记:AJAX 速查表
6.1 各种 AJAX 实现对比
技术 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
原生 XMLHttpRequest | 无需依赖库,兼容性好 | 代码复杂 | 旧项目或需要精确控制的场景 |
jQuery AJAX | 简单易用,兼容性好 | 需要引入 jQuery 库 | 使用 jQuery 的项目 |
Fetch API | 现代 API,基于 Promise | 兼容性较差,错误处理不够直观 | 现代项目 |
Axios | 基于 Promise,自动转换 JSON,拦截器功能强大 | 需要引入额外库 | 大型项目或需要高级功能的场景 |
6.2 常用 API
API | 功能 | 示例 |
---|---|---|
XMLHttpRequest | 原生 AJAX 对象 | const xhr = new XMLHttpRequest(); |
jQuery.ajax() | jQuery AJAX 方法 | $.ajax({ url: '/api', success: function() {...} }); |
fetch() | 现代 AJAX API | fetch('/api').then(response => response.json()); |
axios | 基于 Promise 的 HTTP 客户端 | axios.get('/api').then(response => console.log(response.data)); |