直接用 setInterval + Date.now() 做倒计时不可靠,因页面切后台或系统休眠会导致失准;稳定方案需以服务端下发的考试开始时间戳为基准,客户端校验并本地推算。

直接用 setInterval + Date.now() 做倒计时不可靠,页面切到后台或系统休眠时会失准;真要稳定计时,必须基于服务端下发的考试开始时间戳做客户端校验和本地推算。
倒计时不准?别用 setTimeout 递归模拟时钟
很多人写成这样:
setInterval
- 必须从服务端返回一个权威的
exam_start_time(毫秒时间戳)和总时长(如duration_ms: 3600000) - 前端启动倒计时前,先用
Date.now()和服务端时间比对,计算出本地时钟偏移量(offset = Date.now() - exam_start_time) - 每次渲染都用
Math.max(0, duration_ms - (Date.now() - exam_start_time))实时计算剩余毫秒数,不依赖累计递减
form 提交前必须拦截并禁用所有交互
用户点交卷按钮后如果还能点选项、切题、甚至重复提交,就会引发数据错乱或接口 409 冲突。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 点击交卷后立即设置
document.body.style.pointerEvents = 'none',同时给所有<input>、<textarea></textarea>、<button></button>加disabled属性 - 不要只靠
button.disabled = true—— 用户可能右键“检查元素”删掉 disabled 属性再点,得靠 CSS 阻断事件流 - 提交成功或失败后,统一用
location.replace('/result?sid=xxx')跳转,避免用户刷新重发
单选/多选题状态保存:别等交卷才存,用 localStorage + blur 或 change 触发
网络抖动、意外关闭页面会导致答题进度全丢,光靠表单提交远远不够。
- 每道题绑定
change事件(type="radio"/type="checkbox"),触发时立刻写入localStorage.setItem('exam_answers_' + examId, JSON.stringify(answers)) - 在
beforeunload回调里再强制存一次,覆盖可能未触发的最后操作 - 页面加载时优先从
localStorage恢复答案,再请求服务端比对(防止本地答案过期),冲突时以服务端为准并提示“检测到历史作答,已自动合并”
最麻烦的不是倒计时逻辑,而是用户在最后一秒切到微信回消息,回来发现已交卷——所以倒计时 UI 必须带强提醒(比如最后 60 秒变红+每秒震动),且交卷动作不可逆,任何缓存、还原、撤回都得在服务端严格校验时间戳。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










