日常开发里,我们写Ajax请求是不是总感觉重复代码一堆?
每次都要写new XMLHttpRequest()、监听状态、处理参数、拼接URL……
写多了真的会怀疑人生:我是写业务还是写重复代码啊!
今天咱们就来一步到位封装一个通用ajax()函数,支持GET/POST/PUT/DELETE,自动处理参数,还带三种最常用POST请求格式实战:
application/x-www-form-urlencoded(表单默认)。multipart/form-data(文件上传)。
一、先搞懂:我们要封装的ajax函数长啥样?
我们的目标:一个函数搞定所有请求,只传一个配置对象就行!
支持7个配置项:
- method:请求方式(默认GET,支持GET/POST/PUT/DELETE)。
- params:URL查询参数(拼在?后面的,比如?name=张三&age=18)。
- data:请求体参数(POST/PUT用,放在请求体里)。
- beforeSend:请求发送前的钩子函数,接收xhr对象。
- onSuccess:成功回调(拿到数据干啥你说了算)。
- onError:失败回调(报错了别慌,catch住给提示)。
二、完整版Ajax封装 案例:
/**
* 通用Ajax请求封装函数
* @param {Object} options - 配置对象
* @param {string} options.url - 请求地址【必填】
* @param {string} [options.method='GET'] - 请求方式,默认GET
* @param {Object} [options.params] - URL查询参数,会自动拼接成?key=value
* @param {Object|FormData} [options.data] - 请求体参数(POST/PUT用)
* @param {Function} [options.beforeSend] - 请求发送前的钩子函数,接收xhr对象
* @param {Function} [options.onSuccess] - 请求成功回调
* @param {Function} [options.onError] - 请求失败回调
*/
function ajax(options) {
// 第一步:校验必填参数url,没传直接报错
if (!options.url) {
thrownewError('请求地址url是必填项!你不告诉我地址,我请求谁去?');
}
// 第二步:初始化配置,设置默认值
const {
url,
method = 'GET', // 默认GET请求
params = {},
data = null,
beforeSend, // 请求发送前的钩子
onSuccess = () => {},
onError = () => {}
} = options;
// 第三步:创建XHR对象(Ajax的核心大哥)
const xhr = new XMLHttpRequest();
// 第四步:处理URL参数 —— 把{name:'张三',age:18} 变成 name=张三&age=18
let queryString = '';
// Object.keys拿到params所有key,遍历拼接
const paramsKeys = Object.keys(params);
if (paramsKeys.length > 0) {
queryString = paramsKeys.map(key => {
// encodeURIComponent:处理中文、特殊字符,防止乱码
return`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`;
}).join('&');
// 拼接到URL后面
queryString = '?' + queryString;
}
// 第五步:初始化请求(打开连接)
// 转大写,防止用户传小写get/post
xhr.open(method.toUpperCase(), url + queryString, true);
// 第六步:执行 beforeSend 钩子
// 如果用户传了 beforeSend 并且是函数,就调用它,并把 xhr 对象传给用户使用
if (typeof beforeSend === 'function') {
beforeSend(xhr);
}
// 第七步:监听请求状态变化
xhr.onreadystatechange = function() {
// readyState=4:请求完成
if (xhr.readyState === 4) {
try {
// 状态码2xx都算成功
if (xhr.status >= 200 && xhr.status < 300) {
let responseData;
try {
// 尝试转JSON(绝大多数接口都是JSON)
responseData = JSON.parse(xhr.responseText);
} catch (e) {
// 转失败就用原始文本
responseData = xhr.responseText;
}
// 执行成功回调
onSuccess(responseData);
} else {
// HTTP状态码异常
onError(newError(`请求失败,状态码:${xhr.status}`));
}
} catch (err) {
// 捕获代码异常
onError(err);
}
}
};
// 请求超时/网络错误处理
xhr.ontimeout = () => onError(newError('请求超时!网络开小差了~'));
xhr.onerror = () => onError(newError('网络异常!请检查网络连接~'));
// 第七步:发送请求
// GET请求:send(null),因为参数已经拼在URL里了
if (method.toUpperCase() === 'GET') {
xhr.send(null);
} else {
// POST/PUT/DELETE:发送请求体数据
xhr.send(data);
}
}
三、核心知识点讲解
1. GET 请求为啥 send(null)?
- GET请求没有请求体,所有参数都拼在URL里(
?name=xxx)。
2. POST 请求必须设置 Content-Type!
这是新手最容易踩的坑! 服务器靠Content-Type知道你传的数据是啥格式,不然会解析失败!
四、4种请求+3种POST格式全搞定
案例1:最简单的 GET 请求(查数据)
场景:获取用户列表,带分页参数
// GET 请求 —— 查数据专用
ajax({
url: 'https://xxx.com/api/user/list',
// method默认就是GET,可不写
params: { page: 1, size: 10 }, // 自动拼接成 ?page=1&size=10
onSuccess(res) {
console.log('获取成功!', res);
},
onError(err) {
console.log('获取失败:', err.message);
}
});
案例2:POST 请求 - 表单默认格式(application/x-www-form-urlencoded)
最传统的表单格式,键值对用&连接,浏览器form表单默认就是它!
ajax({
url: 'https://xxx.com/api/user/add',
method: 'POST',
// 必须设置请求头!!!
data: function() {
// 手动把对象转成 name=张三&age=18 格式
const obj = { username: '张三', age: 18 };
returnObject.keys(obj).map(key =>
`${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`
).join('&');
}(),
// 设置请求头
beforeSend(xhr) {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
},
onSuccess(res) {
console.log('提交成功!', res);
}
});
案例3:POST 请求 - 文件上传格式(multipart/form-data)
传文件唯一选择! 不用手动设置请求头,FormData会自动处理!
// 1. 模拟一个文件对象(真实场景用<input type="file">获取)
const file = new File(['前端工程师成长日记'], 'demo.txt', { type: 'text/plain' });
// 2. 创建FormData
const formData = new FormData();
formData.append('nickname', '前端小菜鸟');
formData.append('avatar', file); // 放入文件
// 3. 发送Ajax
ajax({
url: 'https://xxx.com/api/upload',
method: 'POST',
data: formData, // 直接传FormData就行
// 重点:不要手动设置Content-Type!浏览器会自动生成 multipart/form-data
onSuccess(res) {
console.log('上传成功!', res);
}
});
案例4:POST 请求 - JSON格式(application/json)【工作最常用!】
现在90%的后端接口都用JSON格式,必学!
ajax({
url: 'https://xxx.com/api/user/update',
method: 'POST',
// 1. 设置JSON请求头
beforeSend(xhr) {
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
},
// 2. data必须用JSON.stringify转字符串
data: JSON.stringify({
id: 1001,
username: '前端老司机',
job: '前端开发工程师'
}),
onSuccess(res) {
console.log('修改成功!', res);
}
});
五、3种POST格式一张表总结
| | | |
|---|
application/x-www-form-urlencoded | | | key=val&key2=val2 |
multipart/form-data | | | FormData对象 |
application/json | | | JSON字符串 |
六、总结
- 封装Ajax = 少写重复代码 = 摸鱼时间更多。
- POST:必须配
Content-Type,数据放send()里。 - 3种格式:表单用
urlencoded,上传用form-data,接口用json。
阅读原文:原文链接
该文章在 2026/3/23 12:00:52 编辑过