最简可行h5投票页需用localstorage防重复提交、fetch模拟api、label包裹input确保点击有效,提交后禁用选项并实时更新dom;必须加viewport meta、用rem/vw适配、监听pageshow恢复状态。

怎么用纯 HTML + JavaScript 实现一个可运行的 H5 投票页
不能只靠 <form></form> 提交就完事——用户刷新页面会重复投票,后端没接入时连“谁投过”都记不住。最简可行方案是:前端用 localStorage 拦第一道重投,用 fetch 模拟提交(后续替换成真实 API),结构必须支持单选/多选、实时计票、禁用已投选项。
关键不是“画得像投票页”,而是让点击有效、状态可回溯、不误触。以下按真实开发流组织:
- 每个选项用
<label></label>包裹<input type="radio">或<input type="checkbox">,避免点文字不触发 - 投票按钮加
disabled属性初始禁用,仅当有选项被选中才removeAttribute('disabled') - 提交后立即清空选择、禁用所有选项、显示“已投票”,并写入
localStorage.setItem('voted', 'true') - 页面加载时检查
localStorage.getItem('voted') === 'true',命中则隐藏投票区、显示结果区
为什么 localStorage 不能防刷,但必须加
它防不住用户清缓存或换浏览器,但能拦住最常见误操作:手滑连点两次、返回再进重投。不加的话,测试阶段自己都会投出 3 条重复记录。
更严重的是,如果后续对接真实后端,漏掉这层本地拦截,会导致“用户以为没投成功,狂点提交”,后端收到一堆重复请求,还得加幂等性逻辑——本可前端挡住的事,别甩给后端。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
-
localStorage的 key 名建议带项目标识,比如voting_2024_summer,避免和其他页面冲突 - 不要用
localStorage存投票内容(如选了 A 和 C),只存“是否投过”。内容存在后端或内存里更安全 - 若需支持“修改投票”,得额外加“撤回”按钮,并调用
localStorage.removeItem(),同时重置 UI 状态
实时计票怎么做到不卡顿又准确
真正在线活动常有几十人同时刷页面,不能每次渲染都遍历全部选项算百分比。简单做法是:只在提交成功后,从模拟数据或 mock 返回值里取最新统计,一次性更新 DOM。
例如后端返回:
{"total": 127, "options": [{"id": "A", "count": 42}, {"id": "B", "count": 85}]},前端直接按这个画进度条、填数字,不自己加减。
- DOM 更新用
element.textContent而非innerHTML,防 XSS(尤其结果含用户昵称时) - 进度条宽度用
style.width = `${Math.round((count/total)*100)}%`,注意除零保护 - 别在
input的change事件里实时算占比——用户还没提交,算的只是“当前选中态”,不是真实票数
移动端适配最容易漏的三个细节
H5 投票页在 iPhone 上点不动、安卓上字体炸开、横屏错位……往往不是框架问题,是基础 meta 和 CSS 没压住。
- 必须加
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">,尤其user-scalable=no防止用户双指放大后布局崩坏 - 所有文字大小用
rem或vw,禁用px;按钮最小高度设为44px(iOS 触控最小推荐值) -
<input type="radio">默认样式丑且难点击,用appearance: none隐藏原生框,再用::before画圆点,点击区域扩到整个<label></label>
真实上线前,务必用真机测试“锁屏再亮起”后的页面状态——有些安卓机会触发 pageshow 事件但不重跑 JS,导致已投票状态没恢复。这时候得监听 window.addEventListener('pageshow', ...) 做二次检查。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










