如何用JavaScript实现滚动到底部时动态加载后端API数据?
滚动加载公告列表实现方案
我想实现滚动到.notice_content容器底部时,调用后端GET接口获取公告数据,把返回的公告列表追加到容器底部,但作为编程新手,有些功能不知道怎么实现。以下是后端API格式和我目前写的代码,求帮忙完善。
后端API格式
{ "route": "/manager/notices_get", "method": "GET", "param": { "notice_type": "integer/string", // 1=通用公告,2=订单公告 "page": "integer/string" }, "return": { "status": "boolean", "notices": [ { "id": 111, "title": "my name is james" }, { "id": 222, "title": "my name is james" } ] } }
示例请求:获取第二页通用公告
GET /manager/notices_get?page=2¬ice_type=1
现有代码
HTML
<div class="notice_content"> <div class="message">message1</div> <div class="message">message2</div> <div class="message">message3</div> <div class="message">message4</div> </div>
CSS
.notice_content{ width: 300px; height: 150px; overflow-y:auto; border:1px solid #222; } .message{ border:1px solid #ddd; text-align:center; padding:20px; }
JavaScript
// Execute getNotices when scrolling to the bottom let notice_content = document.querySelector('.notice_content'); let isLoading = false; notice_content.onscroll = function(){ if (notice_content.scrollTop + notice_content.clientHeight >= notice_content.scrollHeight && !isLoading) { getNotices(); } } // load message function function getNotices(){ isLoading = true; let page = 1; let noticeType = 1; axios.get("/manager/notices_get?page="+page+"¬ice_type="+ noticeType) .then(res =>{ console.log(res) }) .catch(error => console.log(error)) }
问题分析与修改方案
现有代码的核心问题:
- 页码
page固定为1,无法实现分页加载 - 未处理接口返回数据,无法将新公告追加到容器
- 请求完成后未重置
isLoading状态,后续滚动不会触发加载 - 无更多数据判断逻辑,会重复请求空数据
修改后的完整JavaScript代码
let notice_content = document.querySelector('.notice_content'); let isLoading = false; let currentPage = 1; // 全局维护当前页码 let hasMore = true; // 标记是否还有更多数据 const noticeType = 1; // 固定公告类型,可按需修改 // 滚动监听 notice_content.onscroll = function() { // 滚动接近底部、不在加载中、还有数据时触发加载 if (notice_content.scrollTop + notice_content.clientHeight >= notice_content.scrollHeight - 10 && !isLoading && hasMore) { getNotices(); } }; // 加载公告函数 function getNotices() { isLoading = true; // 添加加载提示 const loadingEl = document.createElement('div'); loadingEl.className = 'message'; loadingEl.textContent = '加载中...'; notice_content.appendChild(loadingEl); axios.get(`/manager/notices_get?page=${currentPage}¬ice_type=${noticeType}`) .then(res => { const { status, notices } = res.data; if (status && notices.length > 0) { // 循环创建公告元素并追加到容器 notices.forEach(notice => { const messageEl = document.createElement('div'); messageEl.className = 'message'; messageEl.textContent = notice.title; messageEl.dataset.id = notice.id; // 存储公告ID,便于后续操作 notice_content.appendChild(messageEl); }); currentPage++; // 页码自增,准备下一页请求 } else { hasMore = false; // 标记无更多数据 const noMoreEl = document.createElement('div'); noMoreEl.className = 'message'; noMoreEl.textContent = '已加载全部公告'; notice_content.appendChild(noMoreEl); } }) .catch(error => { console.error('加载公告失败:', error); const errorEl = document.createElement('div'); errorEl.className = 'message'; errorEl.textContent = '加载失败,请稍后重试'; notice_content.appendChild(errorEl); }) .finally(() => { isLoading = false; // 无论请求成败,重置加载状态 // 移除加载提示 const loadingEl = notice_content.querySelector('.message:last-child'); if (loadingEl && loadingEl.textContent === '加载中...') { notice_content.removeChild(loadingEl); } }); }
关键修改点说明
- 全局页码维护:用
currentPage记录当前请求页码,加载成功后自动自增 - 数据渲染:遍历接口返回的
notices数组,动态创建公告元素并追加到容器 - 加载状态控制:请求开始时锁定加载状态,请求结束后解锁,避免重复请求
- 无更多数据处理:用
hasMore标记,当返回公告为空时停止触发加载 - 滚动触发优化:滚动距离判断时减去10px,解决浏览器精度导致的触发不灵敏问题
- 用户反馈:添加加载中、加载失败、无更多数据的提示,提升体验
内容的提问来源于stack exchange,提问作者WEI A
相关产品推荐
相关产品推荐

