点击加载更多按钮后帖子索引偏移+3模态框数据不匹配问题
帖子加载后模态框数据错位问题修复
问题核心原因
- 事件绑定的元素选择范围错误:你用
document.querySelectorAll("ul")选择元素绑定点击事件时,会把页面内所有<ul>标签都纳入匹配范围,包括模态框里的内容列表、评论列表,根本不是只匹配帖子列表项。加载次数越多,页面里累积的非帖子ul越多,forEach遍历得到的索引偏移量就越大,第三次加载后偏移+3就是页面里多了非帖子类ul标签导致的。 - 重复绑定事件:每次执行
contentLoad()都会给已经渲染过的旧帖子、模态框关闭按钮重复绑定事件,既浪费性能,也会导致事件触发时取值混乱。 - DOM操作位置错误:你把更新帖子容器内容、隐藏加载提示的逻辑写在了for循环内部,每遍历一条帖子就重写一次整个容器的DOM,会造成不必要的性能损耗,也容易触发渲染异常。
修复思路
- 给每个帖子项加专属类名
post-item,渲染时直接把帖子的真实ID、用户ID存在DOM的data-*自定义属性上,点击时直接读取属性取值,完全不依赖元素在页面里的位置索引,从根源避免错位。 - 把HTML拼接和DOM操作拆开:for循环只负责拼接帖子的HTML字符串,全部拼接完成后再一次性插入到帖子容器里,减少DOM重排次数。
- 用事件委托代替逐元素绑定事件:只需要在帖子父容器
.post-content上绑定一次点击监听,动态加载的新帖子会自动响应点击,不需要每次加载都重新绑定,也不会出现重复绑定的问题。 - 模态框关闭按钮的监听单独绑定一次,不要嵌套在帖子点击事件里。
修复后核心代码
fetch(`https://jsonplaceholder.typicode.com/posts`) .then((response) => response.json()) .then((data) => { let count = 12; const postContent = document.querySelector(".post-content"); const myModal = document.getElementById("myModal"); const modalData = document.querySelector(".modal-data"); const modalComments = document.querySelector(".modal-comments"); const loading = document.getElementById("loading"); const loadBtn = document.querySelector(".btn"); const alertTip = document.querySelector(".alert"); // 单独绑定一次模态框关闭事件 document.getElementById("close").addEventListener("click", () => { myModal.style.display = "none"; }); // 事件委托绑定帖子点击事件,仅绑定一次,后续新加载的帖子自动生效 postContent.addEventListener("click", (e) => { // 精准定位点击的帖子项 const postItem = e.target.closest(".post-item"); if (!postItem) return; // 直接从自定义属性读取真实帖子ID,不存在索引错位问题 const postId = Number(postItem.dataset.postId); const post = data.find(item => item.id === postId); // 拉取作者信息 fetch(`https://jsonplaceholder.typicode.com/users/${post.userId}`) .then((response) => response.json()) .then((dataUser) => { // 渲染模态框基础内容 modalData.innerHTML = ` <ul class='list-group my-4'> <li class='list-group-item'><span class='fw-bold'>ID:</span> ${post.id}</li> <li class='list-group-item'><span class='fw-bold'>User Name:</span> ${dataUser.name}</li> <li class='list-group-item'><span class='fw-bold'>Title:</span> ${post.title}</li> <li class='list-group-item'><span class='fw-bold'>Post:</span> ${post.body}</li> <li class='list-group-item'><span class='fw-bold'>Location:</span> ${dataUser.address.city}</li> <li class='list-group-item'><span class='fw-bold'>Company:</span> ${dataUser.company.name}</li> </ul>`; myModal.style.display = "block"; // 拉取对应评论 fetch(`https://jsonplaceholder.typicode.com/comments?postId=${post.id}`) .then((response) => response.json()) .then((dataComment) => { let comments = ""; // 筛选id模3等于0的评论 for (let c = 0; c < dataComment.length; c++) { if (dataComment[c].id % 3 == 0) { comments += ` <ul class='item-group'> <li class='list-group-items'> <span class='fw-bold'>Id:</span> ${dataComment[c].id}</li> <li class='list-group-items'> <span class='fw-bold'>Email:</span> ${dataComment[c].email}</li> <li class='list-group-items'> <span class='fw-bold'>Comment:</span> ${dataComment[c].body}</li> </ul>`; } } modalComments.innerHTML = comments; }) .catch((error) => console.log(error)); }) .catch((error) => console.log(error)); }) function contentLoad() { let showPosts = ""; for (let i = 0; i < count; i++) { // 给帖子项加专属类名,挂载自定义帖子ID属性 showPosts += ` <ul class='list-group my-4 post-item' data-post-id="${data[i].id}"> <li class='list-group-item'><span class='fw-bold'>ID: </span> ${data[i].id}</li> <li class='list-group-item'><span class='fw-bold'>Title: </span> ${data[i].title}</li> <li class='list-group-item'><span class='fw-bold'>Post: </span> ${data[i].body.split(" ").splice(0, 3).join(" ")}</li> </ul>`; } // 循环结束后一次性更新DOM,减少不必要的重绘 postContent.innerHTML = showPosts; loading.style.display = "none"; } // 首次加载帖子 contentLoad(); // 加载更多按钮逻辑 loadBtn.addEventListener("click", function () { count = count + 12; if (count > 96) { loadBtn.style.display = "none"; alertTip.style.display = "block"; } contentLoad(); }); }) .catch((error) => { console.log(error); });
内容的提问来源于stack exchange,提问作者Лука Траиловић
相关产品推荐
相关产品推荐

