基于JS与localStorage的投票系统:替换最少得票设计的实现求助
问题描述
我开发了一个基于JavaScript和localStorage的投票系统,用来存储设计方案及对应票数。现在想实现将得票最少的设计替换为新设计的功能,但目前只能把克隆的新设计添加到DOM开头,导致票数顺序混乱,而且图库设计数量会超过6个。另外,不确定多个设计票数相同时的处理逻辑,求技术帮助。
解决方案
1. 核心重构:优化数据结构
当前用单独变量存储每个票数,扩展性极差。改成数组+对象的结构,把每个设计的信息(票数、样式类、唯一ID)统一管理:
- 用数组存储所有设计的投票数据,每个元素是包含
id、votes、elementClass的对象 - localStorage中用单个键存储整个数组的JSON字符串,替代多个独立的
voteValX键
2. 实现替换逻辑与同票处理
替换流程
- 找出当前票数最低的所有设计
- 从候选中选择一个(默认随机选,公平性更好;也可改成选最先出现/最旧的设计)
- 用新设计的样式替换该位置的设计,重置票数为0
- 更新localStorage并同步DOM
同票处理策略(三选一)
- 随机选择:从所有最低票设计中随机挑一个替换(代码默认采用)
- 优先替换最先出现的:选数组中第一个最低票的设计
- 优先替换最旧的:给每个设计添加
createTime字段,替换时间最早的
完整优化代码
// 初始化投票数据 function initVotingData() { let votingData = localStorage.getItem('votingData'); if (!votingData) { // 初始6个设计,票数默认0 votingData = JSON.stringify([ { id: 1, votes: 0, elementClass: 'red' }, { id: 2, votes: 0, elementClass: 'blue' }, { id: 3, votes: 0, elementClass: 'purple' }, { id: 4, votes: 0, elementClass: 'red' }, { id: 5, votes: 0, elementClass: 'blue' }, { id: 6, votes: 0, elementClass: 'purple' } ]); localStorage.setItem('votingData', votingData); } return JSON.parse(votingData); } let votingData = initVotingData(); const container = $('.container'); // 渲染设计与票数 function renderDesigns() { container.empty(); votingData.forEach((item) => { const designEl = $(`<div class="${item.elementClass} circle"> <span class="voteVal">${item.votes}</span> <button class="voteBtn" data-id="${item.id}">投票</button> </div>`); container.append(designEl); }); bindVoteEvents(); } // 绑定投票点击事件 function bindVoteEvents() { $('.voteBtn').on('click', function() { const id = Number($(this).data('id')); const designItem = votingData.find(item => item.id === id); if (designItem) { designItem.votes++; $(this).siblings('.voteVal').text(designItem.votes); localStorage.setItem('votingData', JSON.stringify(votingData)); } }); } // 重置所有票数 $('.resetAllVotes').on('click', function() { votingData.forEach(item => item.votes = 0); localStorage.setItem('votingData', JSON.stringify(votingData)); renderDesigns(); }); // 主设计颜色切换 $('.btnred').on('click', () => { $("#main").removeClass().addClass("red"); localStorage.setItem('mainDesignClass', 'red'); }); $(".btnblue").on("click", () => { $("#main").removeClass().addClass("blue"); localStorage.setItem('mainDesignClass', 'blue'); }); $(".btnpurple").on("click", () => { $("#main").removeClass().addClass("purple"); localStorage.setItem('mainDesignClass', 'purple'); }); // 替换最低票设计 $(".clone").on("click", function () { // 1. 找出所有最低票设计 const minVotes = Math.min(...votingData.map(item => item.votes)); const lowestVoteDesigns = votingData.filter(item => item.votes === minVotes); // 2. 随机选择一个要替换的设计 const randomTargetIdx = Math.floor(Math.random() * lowestVoteDesigns.length); const targetDesign = lowestVoteDesigns[randomTargetIdx]; const dataIndex = votingData.findIndex(item => item.id === targetDesign.id); // 3. 获取新设计的样式类 const newClass = localStorage.getItem('mainDesignClass') || 'red'; // 4. 更新数据:替换目标设计,重置票数为0 votingData[dataIndex] = { id: Date.now(), // 时间戳做唯一ID votes: 0, elementClass: newClass }; // 5. 同步存储与DOM localStorage.setItem('votingData', JSON.stringify(votingData)); renderDesigns(); }); // 页面初始化 $(document).ready(function() { const mainClass = localStorage.getItem('mainDesignClass') || 'red'; $('#main').addClass(mainClass); renderDesigns(); });
优化亮点
- 数据统一管理:避免大量重复变量,后续调整设计数量只需修改初始数组
- DOM自动同步:数据变化后重新渲染,彻底解决顺序混乱问题
- 灵活扩展:同票处理策略可按需切换,新增功能只需修改对应模块
- 存储高效:单个localStorage键存储所有数据,减少IO操作
内容的提问来源于stack exchange,提问作者alib0ng0
相关产品推荐
相关产品推荐

