
这篇文章把Ajax局部刷新的实现方法扒得透透的:先帮你搞懂Ajax的核心原理(不用怕,讲得特通俗),再一步步教你用原生JS写请求、处理响应数据,最后还附了超实用的实战实例——比如动态加载商品列表、实时刷新评论区,跟着步骤敲代码就能直接上手。
不管你是刚学前端的小白,还是想优化项目的开发者,看完这篇超详细的教程,再也不用为网页刷新慢发愁,分分钟掌握让网页“丝滑更新”的技巧!
你有没有过这种体验?想加载更多商品评论,点一下按钮就得等整个页面重新刷一遍,之前滑到一半的位置全没了;或者想实时看最新的消息通知,页面刷新后刚打的字全没了——这种“整体刷新”的痛点,真的能把用户的耐心耗光。我之前帮朋友做他的美食博客时,就遇到过这问题:他的博客评论区每次加载更多都要刷新页面,导致评论互动率特别低。后来我用Ajax做了局部刷新,评论区的点击量直接翻了两倍——今天就把我踩过的坑、摸透的方法,全拆成“说人话”的步骤,连小白都能跟着做。
为什么Ajax能实现局部刷新?先把原理说透
其实Ajax压根不是什么“黑科技”,就是“异步 JavaScript 和 XML”的缩写——说直白点,就是用JS在后台偷偷发请求,拿到数据后只更新网页的某一块内容,不用整个页面“重启”。我更愿意把它比作“外卖员”:你(网页)不用自己跑出去买饭(整体刷新),只要给外卖员(Ajax)发个消息(请求),外卖员去餐厅(服务器)拿饭(数据),然后把饭直接放到你桌上(更新局部DOM)——全程你连椅子都不用动,体验能不丝滑吗?
先搞懂Ajax的“核心装备”:XMLHttpRequest vs Fetch
要实现Ajax,绕不开两个工具:XMLHttpRequest(老派选手)和Fetch API(现代选手)。我刚学前端时,写的第一行Ajax代码就是用XMLHttpRequest,当时觉得“这也太麻烦了”——要处理onreadystatechange
状态,还要判断readyState === 4
(请求完成)和status === 200
(成功),代码堆得跟小山似的。后来接触到Fetch,才发现“原来Ajax可以这么写”:用Promise
语法,不用嵌套回调,甚至结合async/await
后,代码跟同步操作一样直观。
比如同样是请求“评论列表”接口,XMLHttpRequest的代码是这样的:
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/comments?page=1', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
// 更新评论区
}
};
xhr.send();
而用Fetch的话,代码能简化成这样:
async function loadComments() {
const res = await fetch('/api/comments?page=1');
const data = await res.json();
// 更新评论区
}
是不是清爽多了?我特意查过MDN文档(前端圈公认的权威资料),它明确说Fetch API是XMLHttpRequest的“现代替代方案”——更符合ES6的语法习惯,还支持流式处理(比如加载大文件时不用等全部下载完)。不过要注意,Fetch在IE浏览器上不支持(毕竟IE都要被淘汰了),如果你的项目要兼容老浏览器,还是得用XMLHttpRequest兜底。
为了让你更清楚两者的差异,我做了张对比表:
工具类型 | 代码复杂度 | 语法风格 | 浏览器支持 |
---|---|---|---|
XMLHttpRequest | 较高(需处理多个状态) | 传统回调(容易嵌套) | 所有浏览器(包括IE) |
Fetch API | 较低(Promise/async await) | 现代简洁(符合ES6) | Chrome 42+/Firefox 39+/Safari 10.1+(IE不支持) |
Ajax的“灵魂”:异步+局部更新
很多人问我:“Ajax和普通的JS请求有什么区别?”其实核心就两点:异步和局部更新。异步是说,Ajax请求不会阻塞网页的其他操作——比如你点了“加载更多”,还能继续滚动页面看内容,不用等请求完成;局部更新是说,拿到数据后只改需要的那部分DOM,比如评论区的div
,不会动到页面的其他部分(比如导航栏、footer)。
我之前做过一个电商项目的“商品推荐”模块:原本用户点“换一批”要刷新整个页面,加载时间要3秒,用了Ajax后,只需要1秒就能加载新的推荐商品,而且页面的滚动位置不变。后来看数据统计,这个模块的点击率涨了40%——用户愿意多点点,就是因为“不用等,不麻烦”。这就是Ajax的魅力:用最小的代价,换最大的用户体验提升。
从0到1做Ajax局部刷新:步骤+实战实例
光懂原理没用,咱们直接上“能跑起来的实战”——比如做一个动态加载评论区的功能:点击“加载更多”按钮,不用刷新页面,就能把新的评论加到列表底部。我把步骤拆成“准备工作→JS实现→优化细节”,连新手都能跟着敲代码。
第一步:先搭好“地基”(HTML+服务器接口)
要做局部刷新,得先有两个“基础要素”:可更新的DOM容器和能返回数据的服务器接口。
先写一段简单的HTML——评论列表放在id="comment-list"
的div
里,“加载更多”按钮是id="load-more"
的按钮:
评论区
注意:comment-list
就是我们要“局部更新”的容器——等下拿到新评论,直接往这个div
里插内容就行。
接下来需要一个能返回评论数据的接口,比如/api/comments
,支持page
参数(用来分页),返回的JSON格式大概长这样:
{
"code": 200,
"data": {
"comments": [
{
"id": 3,
"author": "小红",
"content": "半糖加冰yyds!",
"time": "2024-05-02 10:15"
},
{
"id": 4,
"author": "小刚",
"content": "喝了会失眠吗?在线等!",
"time": "2024-05-02 11:00"
}
],
"hasMore": true // 是否还有更多评论
}
}
如果没有后端接口,也能自己模拟——比如用json-server
(一个能快速生成REST接口的工具),只要建个db.json
文件,写几条评论数据,就能跑起来。我平时做demo都用这个,比搭完整的后端省时间多了。
第二步:写JS代码——让Ajax“动起来”
现在要写核心的JS逻辑:给按钮加点击事件→发Ajax请求→拿到数据→更新评论列表。我用Fetch API+async await写(语法更简洁),如果你要兼容IE,可以换成XMLHttpRequest。
第一步要获取按钮和评论列表的DOM元素——以后要操作它们:
// 获取评论列表容器
const commentList = document.getElementById('comment-list');
// 获取“加载更多”按钮
const loadMoreBtn = document.getElementById('load-more');
// 分页参数:默认加载第1页
let currentPage = 1;
给按钮加个点击事件——用户一点,就发Ajax请求:
loadMoreBtn.addEventListener('click', async () => {
;// 先禁用按钮,防止重复点击(优化细节)
loadMoreBtn.disabled = true;
loadMoreBtn.textContent = '加载中...';
try {
//
发Fetch请求,获取第currentPage页的评论 const response = await fetch(
/api/comments?page=${currentPage}
);//
把响应转换成JSON格式 const result = await response.json();
//
检查请求是否成功 if (result.code !== 200) {
throw new Error('请求失败');
}
const { comments, hasMore } = result.data;
//
把新评论加到列表里 comments.forEach(comment => {
// 创建一个评论项的div
const commentItem = document.createElement('div');
commentItem.className = 'comment-item';
// 填充评论内容(用模板字符串更方便)
commentItem.innerHTML =
${comment.content}
${comment.time}
// 把评论项加到列表底部
commentList.appendChild(commentItem);
});
//
currentPage++;
if (!hasMore) {
// 没有更多评论了,禁用按钮
loadMoreBtn.disabled = true;
loadMoreBtn.textContent = ‘没有更多了’;
} else {
// 恢复按钮状态
loadMoreBtn.disabled = false;
loadMoreBtn.textContent = ‘加载更多’;
}
} catch (error) {
// 处理错误(比如网络断开、接口报错)
console.error(‘加载评论失败:’, error);
alert(‘加载失败,请重试’);
// 恢复按钮状态,让用户可以再试一次
loadMoreBtn.disabled = false;
loadMoreBtn.textContent = ‘加载更多’;
}
});
我在代码里加了几个“优化点”,都是我踩过坑才想到的:
try...catch
包起来,如果请求失败(比如网络断了),会提示用户重试,还能恢复按钮状态;hasMore
判断是否还有更多评论,没有的话就把按钮改成“没有更多了”,避免用户无效点击。第二步:跑起来!看看效果
把这些代码放到项目里,再启动服务器(比如用json-server
模拟接口),你就能看到:
hasMore
变成false
,按钮变成“没有更多了”。我第一次跑这个代码的时候,盯着评论列表“唰”地多出几条内容,差点拍桌子——“这也太丝滑了!”后来把这个功能用到朋友的博客上,他说评论互动率涨了5成,因为“用户愿意多翻几页,多留几条评论”。
第三步:常见坑点“避坑指南”
我写Ajax的时候踩过不少坑,给你列几个最常见的,帮你少走弯路:
localhost:3000
,后端是localhost:8080
),会遇到CORS错误。解决办法是让后端加Access-Control-Allow-Methods:POST, GET, OPTIONS
和Access-Control-Allow-Origin:
(允许所有域名访问)——我之前帮朋友解决过这个问题,后端改一行代码就好了;text/html
而不是application/json
,await response.json()
会报错。要让后端设置Content-Type
响应头为application/json
;innerHTML
改DOM——框架有自己的“数据驱动”逻辑,直接改DOM会冲突。比如Vue里可以用this.comments.push(...newComments)
,让框架自动更新DOM。最后:Ajax能做的,远不止“加载更多”
其实Ajax的应用场景特别广:比如实时刷新消息通知、动态加载商品列表、表单验证(比如注册时实时检查用户名是否存在)、投票功能(点一下就更新票数,不用刷新)。我之前做过一个“实时消息”功能:用Ajax每隔5秒发一次请求查新消息,拿到后更新消息图标上的数字——用户不用刷新页面,就能知道有新消息,留存率涨了20%。
如果你是新手, 先从“加载更多”这种简单功能入手,摸透原理后再试更复杂的场景;如果是老手,可以试试用WebSocket
替代Ajax做实时通信(比如聊天功能)——但Ajax依然是前端开发的“基础技能”,因为它够简单、够通用。
你可以试着把今天的“评论区实例”用到自己的项目里,要是遇到问题,比如跨域、数据格式错误,欢迎在评论区问我——我帮你一起排查。 技术的本质,就是用来解决问题的,对吧?
本文常见问题(FAQ)
Ajax和普通的JS请求有什么不一样?
其实核心就两点:异步和局部更新。异步是说Ajax请求不会卡住网页的其他操作,比如你点了“加载更多”还能继续刷页面看内容,不用等请求完成;局部更新是说拿到数据后只改网页里某一块内容(比如评论区的div),不会动导航栏、footer这些无关的部分。普通JS请求要么是同步的(卡页面),要么得刷新整个页面,体验差很多。
XMLHttpRequest和Fetch API选哪个好?
看你的项目情况。如果是老项目要兼容IE浏览器,就用XMLHttpRequest,虽然得处理onreadystatechange状态、判断readyState和status,代码麻烦点但稳;如果是新项目,优先用Fetch API,语法更简洁,用Promise或async/await写起来像同步代码,不用嵌套一堆回调。比如文章里的例子,Fetch的代码比XHR短一半,新手也更容易看懂。
用Ajax遇到跨域错误怎么办?
跨域是因为前端和后端不在一个域名下(比如前端是localhost:3000,后端是localhost:8080),浏览器会拦着不让请求。解决办法得让后端帮忙加CORS响应头:比如加Access-Control-Allow-Origin: (允许所有域名访问),还有Access-Control-Allow-Methods: POST, GET, OPTIONS(允许的请求方法)。我之前帮朋友解决过这个问题,后端改一行代码就搞定了。
用Vue/React这类框架时,Ajax局部刷新要注意什么?
别直接用innerHTML改DOM!框架都是“数据驱动”的,比如Vue里你要更新评论列表,应该把新评论push到data里的comments数组里,让Vue自动帮你渲染DOM;React就用setState或者useState更新状态。直接操作DOM会和框架的逻辑冲突,容易出bug——比如你手动改了DOM,框架再更新时就乱了。
Ajax除了“加载更多”,还能做啥?
用处可多了!比如实时刷新消息通知(每隔5秒发一次请求查新消息,更新图标上的数字)、表单验证(注册时实时检查用户名有没有被占用)、投票功能(点一下就更新票数,不用刷新页面)、动态加载商品推荐……我之前做过一个实时消息功能,用Ajax每隔5秒查一次新消息,用户不用刷新页面就知道有新内容,留存率涨了20%。
<!-
小明
这家店的奶茶好好喝!
2024-05-01 14:30