如何实现点击点赞按钮时为对应帖子而非最新帖子点赞?
解决点击点赞按钮对应帖子点赞的问题
原代码的核心问题是闭包作用域导致事件回调始终引用最后一次循环的post对象,加上重复生成DOM和绑定事件,才会出现点击任何点赞按钮都只给最新帖子点赞的情况。以下是具体修改方案:
关键修改点
- 将重复的
id改为class(如postBox→post-box、likeBtn→like-btn),避免ID冲突 - 生成帖子HTML时,给点赞按钮添加
data-post-id属性存储对应帖子的ID - 把事件绑定逻辑优化,避免闭包变量覆盖问题
- 用
updateDoc替代setDoc,仅更新点赞数字段,无需覆盖整个文档 - 调整DOM生成逻辑,避免在循环内重复更新页面
修改后的完整代码
postSearch.addEventListener("input", async (ev) => { const postsRef = collection(firestore, "posts"); const q = query(postsRef, orderBy("createdAt")); const querySnapshot = await getDocs(q); // 筛选符合搜索条件的帖子,同时初始化未设置likes的字段 const filteredPosts = querySnapshot.docs.filter(async post => { const data = post.data(); if (!data.likes) { await updateDoc(doc(postsRef, post.id), { likes: 0 }); } return data.title.includes(ev.target.value) || data.description.includes(ev.target.value); }); // 生成帖子HTML结构 const items = filteredPosts.reverse().map(post => { const data = post.data(); return ` <div class="post-box"> <h4 class="post-name">${data.display_name}</h4> <h1 class="post-title">${data.title}</h1> <h3 class="post-description">${data.description}</h3> <div class="like-container"> <ion-icon name="thumbs-up-outline" class="like-btn" data-post-id="${post.id}"></ion-icon> <h3 class="like-count">${data.likes || 0}</h3> </div> </div> `; }); // 更新页面内容 postList.innerHTML = items.length ? items.join('') : "no results found"; // 采用事件委托绑定点赞事件,避免重复绑定 postList.addEventListener("click", async (e) => { if (!e.target.classList.contains("like-btn")) return; const postId = e.target.dataset.postId; const postDoc = doc(postsRef, postId); const postSnap = await getDoc(postDoc); if (postSnap.exists()) { const currentLikes = postSnap.data().likes || 0; // 原子递增点赞数,避免并发问题 await updateDoc(postDoc, { likes: currentLikes + 1 }); // 实时更新页面上的点赞数 e.target.nextElementSibling.textContent = currentLikes + 1; } }); });
额外优化说明
如果需要更严谨的并发处理,可以使用Firestore的原子递增函数,先导入increment:
import { increment } from "firebase/firestore";
然后将点赞更新代码替换为:
await updateDoc(postDoc, { likes: increment(1) });
这种方式能确保多用户同时点赞时数据不会出错。
内容的提问来源于stack exchange,提问作者sando xavier
相关产品推荐
相关产品推荐

