Watchlist功能异常:重复影片按钮状态无法同步更新
问题描述
我有一个影片列表,需求是用户点击「Add to my list」按钮时,将对应影片添加至数据库的watchlist表中。目前基础功能正常,但页面中存在重复影片条目,当用户点击添加按钮后,其他重复影片的按钮并未切换为「Remove from my list」状态。我需要实现所有重复影片的按钮同步切换状态,且仅向数据库添加一条记录(如图中黄色圈出的按钮也需切换为「Remove from My List」)。
原代码
const buttons = document.querySelectorAll("button"); buttons.forEach((btn) => { btn.addEventListener("click", (e) => { e.preventDefault(); if (btn.dataset.add) { // Call add item addItemToDB(btn); } else { // Call remove item removeItemFromDB(btn); } }); checkItemExist(btn).then((itemExist) => { if (itemExist) { btn.parentElement.innerHTML = `<button onclick="removeItemFromDB(this)" data-add="false" class="remove-from-watchlist-btn">Remove from My List</button>`; } }); }); async function addItemToDB(btn) { // Check if item exist in DB checkItemExist(btn).then(async (itemExist) => { if (!itemExist) { // Add Item let formData = new FormData(); formData.append("itemId", btn.parentElement.parentElement.dataset.id); formData.append( "itemName", btn.parentElement.previousElementSibling.dataset.name ); formData.append( "itemPoster", btn.parentElement.parentElement.firstElementChild.dataset.poster ); const response = await fetch("request/addItem.php", { method: "POST", body: formData, }); const result = await response.json(); if (result) { btn.parentElement.innerHTML = `<button onclick="removeItemFromDB(this)" data-add="false" class="remove-from-watchlist-btn">Remove from My List</button>`; } } else { console.log("Item exist"); } }); } async function removeItemFromDB(btn) { checkItemExist(btn).then(async (itemExist) => { if (itemExist) { let formData = new FormData(); formData.append("itemId", btn.parentElement.parentElement.dataset.id); formData.append( "itemName", btn.parentElement.previousElementSibling.dataset.name ); const response = await fetch("request/removeItem.php", { method: "POST", body: formData, }); const result = await response.json(); if (result) { btn.parentElement.innerHTML = `<button onclick="addItemToDB(this)" data-add="true" class="add-to-watchlist-btn">Add to My List</button>`; } } }); } async function checkItemExist(btn) { let formData = new FormData(); formData.append("itemId", btn.parentElement.parentElement.dataset.id); formData.append( "itemName", btn.parentElement.previousElementSibling.dataset.name ); const response = await fetch("request/itemExist.php", { method: "POST", body: formData, }); const result = await response.json(); if (result) return true; else return false; }
解决方案
核心逻辑是通过影片ID批量操作所有同影片的按钮,避免只更新当前点击的按钮。以下是具体修改:
1. 新增批量更新按钮状态的函数
创建updateAllMovieButtons函数,根据影片ID找到所有对应容器,统一替换按钮:
function updateAllMovieButtons(itemId, isAdded) { // 找到所有同ID的影片容器 const movieContainers = document.querySelectorAll(`[data-id="${itemId}"]`); movieContainers.forEach(container => { const btnContainer = container.querySelector('button').parentElement; if (isAdded) { btnContainer.innerHTML = `<button data-add="false" class="remove-from-watchlist-btn">Remove from My List</button>`; } else { btnContainer.innerHTML = `<button data-add="true" class="add-to-watchlist-btn">Add to My List</button>`; } }); }
2. 重构增删函数,改用批量更新
去掉嵌套Promise,改用async/await简化逻辑,并在操作成功后调用批量更新函数:
修改后的addItemToDB
async function addItemToDB(btn) { const itemId = btn.parentElement.parentElement.dataset.id; const itemExist = await checkItemExist(btn); if (!itemExist) { const itemName = btn.parentElement.previousElementSibling.dataset.name; const itemPoster = btn.parentElement.parentElement.firstElementChild.dataset.poster; let formData = new FormData(); formData.append("itemId", itemId); formData.append("itemName", itemName); formData.append("itemPoster", itemPoster); const response = await fetch("request/addItem.php", { method: "POST", body: formData, }); const result = await response.json(); if (result) { updateAllMovieButtons(itemId, true); } } else { console.log("Item exist"); } }
修改后的removeItemFromDB
async function removeItemFromDB(btn) { const itemId = btn.parentElement.parentElement.dataset.id; const itemExist = await checkItemExist(btn); if (itemExist) { const itemName = btn.parentElement.previousElementSibling.dataset.name; let formData = new FormData(); formData.append("itemId", itemId); formData.append("itemName", itemName); const response = await fetch("request/removeItem.php", { method: "POST", body: formData, }); const result = await response.json(); if (result) { updateAllMovieButtons(itemId, false); } } }
3. 初始化逻辑优化
用事件委托绑定点击事件(避免动态生成按钮丢失绑定),并批量初始化同ID影片的按钮状态,减少重复请求:
async function initWatchlistButtons() { // 收集唯一影片ID,避免重复请求 const uniqueMovieIds = new Set(); document.querySelectorAll('[data-id]').forEach(container => { uniqueMovieIds.add(container.dataset.id); }); // 批量初始化每个影片的按钮状态 for (const itemId of uniqueMovieIds) { const firstBtn = document.querySelector(`[data-id="${itemId}"] button`); if (firstBtn) { const itemExist = await checkItemExist(firstBtn); updateAllMovieButtons(itemId, itemExist); } } // 事件委托绑定点击事件 document.addEventListener('click', (e) => { const btn = e.target.closest('button'); if (!btn) return; e.preventDefault(); if (btn.dataset.add === 'true') { addItemToDB(btn); } else { removeItemFromDB(btn); } }); } // 页面加载完成后初始化 document.addEventListener('DOMContentLoaded', initWatchlistButtons);
完整修改后代码
// 批量更新同ID影片的按钮状态 function updateAllMovieButtons(itemId, isAdded) { const movieContainers = document.querySelectorAll(`[data-id="${itemId}"]`); movieContainers.forEach(container => { const btnContainer = container.querySelector('button').parentElement; if (isAdded) { btnContainer.innerHTML = `<button data-add="false" class="remove-from-watchlist-btn">Remove from My List</button>`; } else { btnContainer.innerHTML = `<button data-add="true" class="add-to-watchlist-btn">Add to My List</button>`; } }); } // 检查影片是否已在列表中 async function checkItemExist(btn) { const itemId = btn.parentElement.parentElement.dataset.id; const itemName = btn.parentElement.previousElementSibling.dataset.name; let formData = new FormData(); formData.append("itemId", itemId); formData.append("itemName", itemName); const response = await fetch("request/itemExist.php", { method: "POST", body: formData, }); const result = await response.json(); return Boolean(result); } // 添加影片到列表 async function addItemToDB(btn) { const itemId = btn.parentElement.parentElement.dataset.id; const itemExist = await checkItemExist(btn); if (!itemExist) { const itemName = btn.parentElement.previousElementSibling.dataset.name; const itemPoster = btn.parentElement.parentElement.firstElementChild.dataset.poster; let formData = new FormData(); formData.append("itemId", itemId); formData.append("itemName", itemName); formData.append("itemPoster", itemPoster); const response = await fetch("request/addItem.php", { method: "POST", body: formData, }); const result = await response.json(); if (result) { updateAllMovieButtons(itemId, true); } } else { console.log("Item exist"); } } // 从列表移除影片 async function removeItemFromDB(btn) { const itemId = btn.parentElement.parentElement.dataset.id; const itemExist = await checkItemExist(btn); if (itemExist) { const itemName = btn.parentElement.previousElementSibling.dataset.name; let formData = new FormData(); formData.append("itemId", itemId); formData.append("itemName", itemName); const response = await fetch("request/removeItem.php", { method: "POST", body: formData, }); const result = await response.json(); if (result) { updateAllMovieButtons(itemId, false); } } } // 初始化页面 async function initWatchlistButtons() { // 收集唯一影片ID,避免重复请求 const uniqueMovieIds = new Set(); document.querySelectorAll('[data-id]').forEach(container => { uniqueMovieIds.add(container.dataset.id); }); // 批量初始化每个影片的按钮状态 for (const itemId of uniqueMovieIds) { const firstBtn = document.querySelector(`[data-id="${itemId}"] button`); if (firstBtn) { const itemExist = await checkItemExist(firstBtn); updateAllMovieButtons(itemId, itemExist); } } // 事件委托绑定点击事件 document.addEventListener('click', (e) => { const btn = e.target.closest('button'); if (!btn) return; e.preventDefault(); if (btn.dataset.add === 'true') { addItemToDB(btn); } else { removeItemFromDB(btn); } }); } // 页面加载完成后初始化 document.addEventListener('DOMContentLoaded', initWatchlistButtons);
内容的提问来源于stack exchange,提问作者Tony Vito
相关产品推荐
相关产品推荐

