JavaScript单选按钮选中项存入数组与localStorage出现重复值问题
问题分析与解决方案
重复值出现的核心原因
- 事件监听重复绑定:每次调用
showMovies(初始化、搜索时)都会给main元素新增一个click事件监听,点击按钮时所有已绑定的监听函数都会执行,导致同一值被多次推入数组。 - 单选按钮未正确配置:使用
type="radio"但未设置相同的name属性,导致按钮彼此独立,既无法实现单选互斥,还会允许重复点击触发多次添加操作。 - 数组无去重逻辑:即使修复事件绑定,重复点击同一按钮时,仍会重复添加相同内容到数组。
修复步骤与代码
1. 移除重复的事件监听
将click事件监听移到showMovies函数外部,只绑定一次,避免重复触发。
2. 调整按钮类型(单选/多选)
- 如果需要多选电影:将
type="radio"改为type="checkbox",支持同时选中多个条目。 - 如果需要单选一组:给所有单选按钮添加相同的
name属性(比如name="fav-movie"),确保同一时间只能选中一个,数组仅保留当前选中项。
3. 添加数组去重与状态同步逻辑
点击时判断当前电影是否已在数组中:多选场景下,选中则添加、取消则移除;单选场景下直接替换数组内容。
修复后的完整代码
const main = document.getElementById("main"); const form = document.getElementById("form"); const search = document.getElementById("search"); let arr = []; // 从localStorage初始化数组,刷新页面保留选中状态 const savedArr = localStorage.getItem('test'); if (savedArr) { arr = JSON.parse(savedArr); } showMovies(apiUrl); function showMovies(url) { main.innerHTML = ""; // 清空旧内容,避免重复渲染 fetch(url) .then((res) => res.json()) .then(function (data) { data.results.forEach((element) => { let movYear = new Date(element.release_date); const el = document.createElement("div"); const image = document.createElement("img"); const title = document.createElement("h2"); const year = document.createElement("h2"); const rank = document.createElement("h2"); const node = document.createTextNode("Favourite: "); const wrapper = document.createElement("h2"); const fav = document.createElement("INPUT"); title.classList.add("title"); // 改为checkbox支持多选,如需单选则保留radio并添加name属性 fav.setAttribute("type", "checkbox"); fav.setAttribute("id", element.id); fav.classList.add("fav"); // 单选场景添加:fav.setAttribute("name", "fav-movie"); // 初始化时同步localStorage中的选中状态 const movieTitle = element.title.trim(); if (arr.includes(movieTitle)) { fav.checked = true; } wrapper.insertBefore(node, wrapper.children[0]); wrapper.appendChild(fav); title.innerHTML = `Title: ${element.title}`; year.innerHTML = `Release: ${movYear.getFullYear()}`; rank.innerHTML = `Rating: ${element.popularity}`; image.src = IMGPATH + element.poster_path; el.appendChild(image); el.appendChild(title); el.appendChild(year); el.appendChild(rank); el.appendChild(wrapper); main.appendChild(el); }); }); } // 仅绑定一次点击事件 main.addEventListener("click", function(e) { const tgt = e.target; if (tgt.matches(".fav")) { const movieTitle = tgt.closest("div").querySelector("h2.title").textContent.slice(6).trim(); const index = arr.indexOf(movieTitle); if (tgt.type === "checkbox") { // 多选逻辑:选中添加,取消移除 tgt.checked ? index === -1 && arr.push(movieTitle) : index !== -1 && arr.splice(index, 1); } else if (tgt.type === "radio") { // 单选逻辑:直接替换为当前选中项 arr = [movieTitle]; } localStorage.setItem('test', JSON.stringify(arr)); } }); form.addEventListener("submit", (e) => { e.preventDefault(); main.innerHTML = ""; const searchTerm = search.value.trim(); searchTerm ? showMovies(SEARCHAPI + searchTerm) : showMovies(apiUrl); search.value = ""; });
关键修改点说明
- 事件监听移到外部,避免重复绑定导致多次触发。
- 调整按钮类型或添加
name属性,适配单选/多选需求。 - 新增localStorage初始化与状态同步,刷新页面保留选中记录。
- 点击时判断条目是否已存在,实现添加/移除的双向同步,彻底解决重复值问题。
内容的提问来源于stack exchange,提问作者user15174190
相关产品推荐
相关产品推荐

