You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript单选按钮选中项存入数组与localStorage出现重复值问题

问题分析与解决方案

重复值出现的核心原因

  1. 事件监听重复绑定:每次调用showMovies(初始化、搜索时)都会给main元素新增一个click事件监听,点击按钮时所有已绑定的监听函数都会执行,导致同一值被多次推入数组。
  2. 单选按钮未正确配置:使用type="radio"但未设置相同的name属性,导致按钮彼此独立,既无法实现单选互斥,还会允许重复点击触发多次添加操作。
  3. 数组无去重逻辑:即使修复事件绑定,重复点击同一按钮时,仍会重复添加相同内容到数组。

修复步骤与代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 07:24:22