0%

Ajax

Ajax 技术详解:从原生实现到 jQuery 封装及实战应用

Ajax(Asynchronous JavaScript and XML)是现代网页交互的核心技术,它通过在后台与服务器进行异步数据交换,使网页能够在不重新加载整个页面的情况下更新部分内容,显著提升了用户体验。本文将从 “原生 XMLHttpRequest 实现→JSON 数据处理→jQuery 简化方案→实战场景” 四个维度,系统讲解 Ajax 技术的原理与应用,帮你彻底掌握前后端异步通信的核心方法。

原生 Ajax:XMLHttpRequest 对象详解

原生 Ajax 基于 XMLHttpRequest(XHR)对象实现,它是浏览器提供的内置 API,用于在客户端与服务器之间建立异步通信。理解 XHR 的工作原理,是掌握 Ajax 技术的基础。

1. XHR 对象的创建

不同浏览器对 XHR 的实现略有差异(主要是早期 IE 浏览器),标准创建方式如下:

1
2
3
4
5
6
7
8
9
// 标准创建方法(兼容现代浏览器及 IE7+)
var xhr;
if (window.XMLHttpRequest) {
// 现代浏览器(Chrome、Firefox、Edge 等)
xhr = new XMLHttpRequest();
} else {
// 兼容 IE6 及以下(使用 ActiveX 对象)
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}

注意:目前主流浏览器(包括 IE7+)均支持标准的 XMLHttpRequest,IE6 及以下已极少使用,实际开发中可简化为 var xhr = new XMLHttpRequest();

2. XHR 对象的核心属性与方法

XHR 对象通过一系列方法发送请求,并通过属性和事件处理服务器响应,核心成员如下:

类型 名称 作用描述
方法 open(method, url) 初始化请求:method 为请求方法(GET/POST 等),url 为请求地址
send(content) 发送请求:content 为请求体(GET 请求通常为 null,POST 请求为表单数据或 JSON)
setRequestHeader(header, value) 设置请求头(需在 open() 之后、send() 之前调用)
属性 readyState 请求状态码(0-4):0 = 未初始化,1 = 加载中,2 = 已加载,3 = 交互中,4 = 完成
status 服务器响应的 HTTP 状态码(如 200 = 成功,404 = 未找到,500 = 服务器错误)
statusText HTTP 状态码对应的文本描述(如 “OK”、”Not Found”)
responseText 服务器返回的文本数据(字符串格式)
responseXML 服务器返回的 XML 数据(XML 文档对象,较少使用)
事件 onreadystatechange readyState 变化时触发的事件处理器(核心回调函数)

3. 发送 GET 请求(获取数据)

GET 请求适用于 “从服务器获取数据”,参数通过 URL query 字符串传递(如 url?key1=value1&key2=value2)。

完整流程示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 1. 创建 XHR 对象
var xhr = new XMLHttpRequest();

// 2. 配置请求(GET 方法,带参数)
var url = "http://localhost:8080/api/user";
var params = "id=123&name=张三"; // 请求参数
xhr.open("GET", url + "?" + params, true); // 第三个参数 true 表示异步请求

// 3. 设置请求头(GET 请求可选,默认已包含必要头信息)
// xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

// 4. 定义状态变化回调函数
xhr.onreadystatechange = function() {
// 仅当请求完成(readyState=4)且成功(status=200)时处理响应
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// 服务器返回的数据(字符串)
console.log("响应内容:", xhr.responseText);
// 解析为 JSON 对象(假设服务器返回 JSON)
var data = JSON.parse(xhr.responseText);
console.log("解析后的数据:", data);
} else {
// 处理错误(如 404、500)
console.error("请求失败,状态码:", xhr.status);
}
}
};

// 5. 发送请求(GET 请求无请求体,参数为 null)
xhr.send(null);
关键注意:
  • GET 请求参数会暴露在 URL 中,不适合传递敏感数据(如密码);
  • URL 长度有限制(不同浏览器略有差异,通常不超过 2048 字符),大量数据建议用 POST;
  • 浏览器对 GET 请求有缓存机制,若需禁用缓存,可添加随机参数(如 ?t=123456,值为时间戳)。

4. 发送 POST 请求(提交数据)

POST 请求适用于 “向服务器提交数据”(如表单提交、新增数据),参数放在请求体中,安全性高于 GET。

完整流程示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 1. 创建 XHR 对象
var xhr = new XMLHttpRequest();

// 2. 配置请求(POST 方法)
var url = "http://localhost:8080/api/user";
xhr.open("POST", url, true);

// 3. 设置请求头(POST 请求必须指定 Content-Type)
// 表单格式(默认,适合普通表单数据)
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 若服务器接收 JSON 格式,需改为:
// xhr.setRequestHeader("Content-Type", "application/json");

// 4. 定义状态变化回调函数
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log("提交成功:", JSON.parse(xhr.responseText));
} else {
console.error("提交失败:", xhr.statusText);
}
}
};

// 5. 准备请求体数据并发送
// 表单格式数据(与 Content-Type 对应)
var formData = "name=张三&age=25&email=zhangsan@example.com";
// 若为 JSON 格式,需转为字符串:
// var jsonData = JSON.stringify({name: "张三", age: 25});

xhr.send(formData); // 发送表单数据
// xhr.send(jsonData); // 发送 JSON 数据
关键注意:
  • POST 请求必须设置 Content-Type 头,否则服务器可能无法正确解析数据;
  • 表单格式(application/x-www-form-urlencoded)适用于普通键值对数据,JSON 格式(application/json)适用于复杂对象;
  • POST 请求无 URL 长度限制,适合传递大量数据或敏感信息(需配合 HTTPS)。

JSON 数据处理:前后端数据交换的通用格式

JSON(JavaScript Object Notation)是 Ajax 中最常用的数据交换格式,它轻量、易读、易解析,优于早期的 XML。

1. JSON 的两种形式

JSON 在 JavaScript 中有两种存在形式,需根据场景正确转换:

形式 描述 用途
JSON 对象 符合 JSON 语法的 JavaScript 对象 用于 JavaScript 内部处理(直接访问属性)
JSON 字符串 符合 JSON 语法的字符串(键值用双引号) 用于网络传输(请求体、响应体)或本地存储
示例:
1
2
3
4
5
6
7
8
9
10
11
// 1. JSON 对象(JavaScript 内部使用)
var userObj = {
"id": 1,
"name": "张三",
"age": 25,
"hobbies": ["篮球", "编程"]
};
console.log(userObj.name); // 直接访问属性:"张三"

// 2. JSON 字符串(网络传输用)
var userStr = '{"id": 1, "name": "张三", "age": 25}'; // 注意:键和字符串值必须用双引号

2. JSON 与字符串的转换

(1)JSON 对象 → JSON 字符串(序列化)

使用 JSON.stringify() 方法,将 JSON 对象转为字符串(用于发送请求时的请求体):

1
2
3
var userObj = {name: "张三", age: 25};
var userStr = JSON.stringify(userObj);
console.log(userStr); // 输出:'{"name":"张三","age":25}'
(2)JSON 字符串 → JSON 对象(反序列化)

使用 JSON.parse() 方法,将字符串转为 JSON 对象(用于处理服务器返回的响应数据):

1
2
3
var userStr = '{"name":"张三","age":25}';
var userObj = JSON.parse(userStr);
console.log(userObj.age); // 输出:25
注意:避免使用 eval()

eval("(" + jsonStr + ")") 是早期解析 JSON 的方法,但存在严重安全风险(eval 会执行字符串中的任意代码),现代开发中必须使用 JSON.parse()

1
2
3
4
5
6
// 不推荐:eval 存在安全风险
var jsonStr = '{"name":"李四"}';
var data = eval("(" + jsonStr + ")"); // 不推荐!

// 推荐:使用 JSON.parse()
var data = JSON.parse(jsonStr); // 安全可靠

jQuery 简化 Ajax 操作

原生 XHR 代码繁琐且需处理浏览器兼容,jQuery 封装了一系列 Ajax 方法(load()$.get()$.post()$.ajax()),大幅简化了异步请求的编写。

1. load() 方法:加载 HTML 并插入 DOM

load() 是 jQuery 中最简单的 Ajax 方法,用于 “请求远程 HTML 片段并直接插入到指定元素中”,无需手动处理 DOM 插入。

语法:
1
$(selector).load(url [, data] [, callback]);
  • selector:目标元素(数据加载后插入此处);
  • url:请求地址;
  • data(可选):发送到服务器的参数(对象或字符串);
  • callback(可选):请求完成后的回调函数。
示例:加载远程页面片段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- 目标元素:加载后插入这里 -->
<div id="content"></div>

<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
<script>
// 加载 remote.html 并插入到 #content
$("#content").load("remote.html", function(response, status, xhr) {
// 回调函数参数:
// response:服务器返回的 HTML 字符串
// status:请求状态("success"、"error"、"timeout" 等)
// xhr:XHR 对象
if (status === "success") {
console.log("HTML 加载成功");
} else {
console.error("加载失败:", xhr.status);
}
});
</script>
关键特点:
  • 默认使用 GET 请求,若提供 data 则自动转为 POST;
  • 直接将服务器返回的 HTML 插入到目标元素,适合简单页面片段复用;
  • 不适合处理 JSON 数据(需手动解析,推荐用 $.get()$.ajax())。

2. $.get() 方法:发送 GET 请求获取数据

$.get() 专门用于发送 GET 请求,适合 “从服务器获取数据”(如查询列表、详情),需手动处理响应数据。

语法:
1
$.get(url [, data] [, success] [, dataType]);
  • url:请求地址;
  • data(可选):请求参数(对象,自动转为 query 字符串);
  • success(可选):请求成功的回调函数;
  • dataType(可选):预期的响应数据类型("json""text""html")。
示例:获取用户列表(JSON 数据)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 发送 GET 请求获取用户列表
$.get(
"api/user-list", // 接口地址
{page: 1, size: 10}, // 请求参数(page=1&size=10)
function(data, status, xhr) {
// data:根据 dataType 解析后的数据(此处为 JSON 对象)
if (data.code === 200) {
console.log("用户列表:", data.data);
// 渲染数据到页面(示例)
var html = "";
data.data.forEach(user => {
html += `<li>${user.name}${user.age}岁)</li>`;
});
$("#userList").html(html);
} else {
alert("获取失败:" + data.msg);
}
},
"json" // 指定响应数据类型为 JSON(自动解析)
);

3. $.post() 方法:发送 POST 请求提交数据

$.post() 专门用于发送 POST 请求,适合 “向服务器提交数据”(如表单提交、新增数据),参数在请求体中传递。

语法:
1
$.post(url [, data] [, success] [, dataType]);

参数与 $.get() 一致,唯一区别是请求类型为 POST

示例:提交表单数据(新增用户)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<form id="userForm">
<input type="text" name="name" placeholder="姓名">
<input type="number" name="age" placeholder="年龄">
<button type="submit">提交</button>
</form>

<script>
$("#userForm").submit(function(e) {
e.preventDefault(); // 阻止表单默认提交(避免页面刷新)

// 获取表单数据(转为对象)
var formData = {
name: $("input[name='name']").val(),
age: $("input[name='age']").val()
};

// 发送 POST 请求
$.post(
"api/user", // 接口地址
formData, // 请求体数据
function(data) {
if (data.code === 200) {
alert("新增成功,ID:" + data.data.id);
$(this)[0].reset(); // 重置表单
} else {
alert("新增失败:" + data.msg);
}
}.bind(this), // 绑定 this 为表单元素
"json" // 响应数据类型为 JSON
);
});
</script>

4. $.ajax() 方法:底层全功能接口(推荐)

$.ajax() 是 jQuery Ajax 的底层方法,支持 GET、POST 等所有 HTTP 方法,可配置超时、请求头、错误处理等高级功能,能覆盖上述所有方法的场景。

核心配置项:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$.ajax({
url: "请求地址", // 必选
type: "GET", // 请求方法(GET/POST/DELETE 等)
data: {key: "value"}, // 请求参数(对象或字符串)
dataType: "json", // 预期响应数据类型
contentType: "application/x-www-form-urlencoded", // 请求体格式
timeout: 5000, // 超时时间(毫秒)
beforeSend: function(xhr) { // 请求发送前的回调(可设置请求头)
xhr.setRequestHeader("Authorization", "Bearer token");
},
success: function(data) { // 成功回调
console.log("成功:", data);
},
error: function(xhr, status, error) { // 失败回调
console.error("失败:", status, error);
},
complete: function(xhr, status) { // 完成回调(无论成功/失败)
console.log("请求完成");
}
});
示例:发送 JSON 格式的 POST 请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 发送 JSON 格式数据(前后端分离常用)
$.ajax({
url: "api/user",
type: "POST",
data: JSON.stringify({name: "张三", age: 25}), // JSON 字符串
contentType: "application/json", // 声明请求体为 JSON
dataType: "json",
success: function(data) {
alert("新增成功");
},
error: function(xhr) {
alert("错误:" + xhr.responseJSON?.msg || "网络异常");
}
});

Ajax 实战场景与常见问题

1. 实战场景:实时搜索提示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<input type="text" id="searchInput" placeholder="输入关键词搜索...">
<ul id="suggestList"></ul>

<script>
var timer; // 用于防抖的定时器
$("#searchInput").input(function() {
var keyword = $(this).val().trim();
var $suggestList = $("#suggestList");

// 防抖:输入停止 300ms 后再发送请求,避免频繁请求
clearTimeout(timer);
timer = setTimeout(function() {
if (!keyword) {
$suggestList.empty().hide();
return;
}

// 发送 GET 请求获取搜索提示
$.get(
"api/search/suggest",
{keyword: keyword},
function(data) {
if (data.code === 200 && data.data.length > 0) {
var html = "";
data.data.forEach(item => {
html += `<li>${item}</li>`;
});
$suggestList.html(html).show();
} else {
$suggestList.html("<li>无匹配结果</li>").show();
}
},
"json"
);
}, 300);
});
</script>

2. 常见问题与解决方案

(1)跨域请求被阻止(CORS 错误)

现象:浏览器控制台报错 Access to XMLHttpRequest at 'http://api.example.com' from origin 'http://localhost' has been blocked by CORS policy

原因:浏览器的同源策略限制(协议、域名、端口任一不同即为跨域),服务器未允许当前域名访问。

解决方案

  • 服务器配置 CORS(推荐):在响应头中添加 Access-Control-Allow-Origin: http://localhost(允许指定域名);
  • JSONP(仅支持 GET):利用 <script> 标签不受同源限制的特性,适合老系统兼容;
  • 代理服务器:开发环境可通过 Webpack、Nginx 等配置代理,将跨域请求转为同域请求。
(2)JSON 解析错误(JSON.parse: unexpected character

现象JSON.parse(xhr.responseText) 报错,或 jQuery 指定 dataType: "json" 时进入 error 回调。

原因

  • 服务器返回的不是 valid JSON(如 HTML 错误页面、格式错误的 JSON);
  • 响应数据包含多余空格、注释(JSON 不支持注释)。

解决方案

  • 查看服务器响应:在浏览器 “开发者工具 → Network → 对应请求 → Response” 中检查返回内容;
  • 若返回 HTML 错误(如 404 页面),检查请求 URL 是否正确;
  • 协调后端确保返回标准 JSON 格式(无注释、引号正确、逗号分隔正确)。
(3)请求超时无反馈

现象:网络缓慢时,请求长时间无响应,用户不知道是否成功。

解决方案

  • 设置超时时间(原生 XHR 的 timeout 属性,jQuery 的 timeout 配置);
  • 显示加载状态(请求发送时显示 “加载中”,完成后隐藏)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// jQuery 示例:带超时和加载状态
$("#submitBtn").click(function() {
var $btn = $(this).text("提交中...").prop("disabled", true);
var $loading = $("#loading").show();

$.ajax({
url: "api/submit",
type: "POST",
data: {content: "test"},
timeout: 5000, // 5 秒超时
success: function() {
alert("提交成功");
},
error: function(xhr, status) {
if (status === "timeout") {
alert("请求超时,请重试");
} else {
alert("提交失败");
}
},
complete: function() {
$btn.text("提交").prop("disabled", false);
$loading.hide();
}
});
});

总结与最佳实践

1. 核心总结

  • 原生 Ajax:基于 XMLHttpRequest 对象,需手动处理请求发送、状态监听、数据解析,适合理解原理;
  • JSON 处理:用 JSON.stringify() 序列化、JSON.parse() 反序列化,避免使用 eval()
  • jQuery 简化load() 适合加载 HTML 片段,$.get()/$.post() 适合简单请求,$.ajax() 适合复杂场景(推荐);
  • 关键问题:跨域用 CORS 或代理,解析错误检查响应格式,超时需设置超时时间并反馈用户。

2. 最佳实践建议

  1. 封装公共 Ajax 函数:统一处理请求头(如 Token 认证)、错误提示、加载状态,减少重复代码;
  2. 使用防抖 / 节流:对于输入框实时搜索等场景,用防抖(延迟请求)或节流(限制请求频率)减少服务器压力;
  3. 优先使用 HTTPS:敏感数据(如用户信息、Token)必须通过 HTTPS 传输,防止数据泄露;
  4. 处理离线状态:通过 navigator.onLine 判断网络状态,离线时提示用户;
  5. 现代替代方案:熟悉 Fetch API(原生,基于 Promise)和 Axios(第三方库,功能更全),它们是 jQuery Ajax 的现代替代品,更适合现代前端开发

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10