使用jQuery和PHP实现无限滚动时,加载完最后数据后重复加载问题
无限滚动加载重复内容的问题修复
问题分析
你的无限滚动出现重复内容的核心原因有两个:
- 前端加载逻辑错误:每次请求后同时递增
offset和amount,导致每次加载的数量越来越大(第一次10条,第二次20条,第三次30条...),当offset超过数据库总数据量时仍会持续触发请求;且未判断返回数据是否为空,无法终止后续加载。 - 后端查询无排序:SQL语句未添加
ORDER BY,MySQL在无排序条件下返回的结果顺序可能不稳定,极端情况会出现重复数据。
修复后的代码
前端(index.html jQuery代码)
<script type="text/javascript"> var offset = 0; const amount = 10; // 固定每次加载10条,不再递增 var working = false; var hasMore = true; // 标记是否还有更多数据 $(document).ready(function () { loadPrompts(); }); $(window).scroll(function () { if (hasMore && !working && $(this).scrollTop() + 1 >= $("body").height() - $(window).height()) { loadPrompts(); } }); // 封装加载函数,避免重复代码 function loadPrompts() { working = true; $.ajax({ type: "GET", url: `showcase.php?offset=${offset}&amount=${amount}`, success: function (r) { const data = JSON.parse(r); if (data.length === 0) { hasMore = false; // 没有更多数据,停止加载 working = false; return; } // 追加图片到页面 data.forEach(item => { $("body").append(`<img src="${item.cover_url}" />`); }); offset += amount; // 只递增offset,amount保持固定 setTimeout(() => { working = false; }, 100); }, error: function () { console.log("Something went wrong!"); working = false; }, }); } </script>
后端(showcase.php代码)
include_once("classes/Db.php"); class Prompt { public static function filter($offset, $limit){ $conn = Db::getInstance(); // 添加ORDER BY确保结果顺序稳定,这里假设主键是id,按id升序排列 $stmt = $conn->prepare("SELECT * FROM prompts ORDER BY id ASC LIMIT :offset, :limit"); // 绑定参数,避免SQL注入 $stmt->bindParam(':offset', $offset, PDO::PARAM_INT); $stmt->bindParam(':limit', $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } } $offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0; $amount = isset($_GET['amount']) ? (int)$_GET['amount'] : 10; $prompts = Prompt::filter($offset, $amount); echo json_encode($prompts);
关键修复点
- 前端:固定每次加载的数量,添加
hasMore标记判断是否还有数据,当返回空数组时停止触发后续请求;封装加载函数减少重复代码。 - 后端:添加
ORDER BY保证数据顺序稳定,使用参数绑定避免SQL注入,同时对GET参数做类型转换,防止非法输入。
内容的提问来源于stack exchange,提问作者Tibo Mertens
相关产品推荐
相关产品推荐

