Node.js结合Pug实现点击按钮展示新测验题、清除旧题目的方法
简易在线测验实现方案
核心交互逻辑
要实现「点击按钮展示新题、自动移除旧题」的效果,最轻量化的实现不需要每次点击都请求后端:
- 后端一次性把题库传到前端页面
- 前端维护当前展示的题目索引,点击按钮时更新索引,直接替换页面对应位置的文本,旧内容会被自然覆盖移除
- 修正原有代码里的变量拼写、重复响应导致的服务报错问题
代码调整
后端 index.js
原有代码的问题:循环里多次调用res.render是无效操作,Express的响应对象只能向客户端返回一次结果,重复调用会直接抛出「响应头已发送」的报错;同时存在变量拼写错误,遍历数组questions时取值错写成question[i],会触发未定义变量的报错。
调整后的完整代码:
const express = require('express') const app = express() app.set('view engine', 'pug') app.use(express.urlencoded({ extended: false })) // 预先定义测验题库 const questionBank = [ '以下哪个属于JavaScript的原始数据类型?', 'HTTP状态码403代表什么含义?', 'CSS中哪个属性可以设置元素的圆角?' ] app.get('/', (req, res) => { // 单次调用render,把全量题库传给前端模板 res.render('index', { questions: questionBank }) }) app.listen(3000, () => { console.log('服务已启动,访问3000端口即可') })
前端模板 index.pug
原有代码的问题:一方面受后端循环渲染影响,模板最终只会拿到最后一道题的固定值,点击按钮永远只会显示同一句话;另一方面把单道题目的插值直接写在点击事件函数里,根本没有存全量题库到前端,完全没法实现多题切换。需要把题库注入到前端JS环境,通过事件监听实现索引更新和DOM替换。
调整后的完整代码:
html(lang="zh-CN") head meta(charset="UTF-8") meta(http-equiv="X-UA-Compatible", content="IE=edge") meta(name="viewport", content="width=device-width, initial-scale=1.0") title 简易在线测验 body h1#question-display button#next-btn 显示下一题 script. // 把后端传的题库转成前端可直接使用的JS数组 const questionList = !{JSON.stringify(questions)} // 维护当前题目的展示位置,初始为-1,第一次点击展示第一题 let currentIndex = -1 // 获取对应的DOM元素 const questionArea = document.getElementById('question-display') const nextBtn = document.getElementById('next-btn') nextBtn.addEventListener('click', () => { // 索引递增,到题库末尾自动回到第一题,实现循环答题 currentIndex = (currentIndex + 1) % questionList.length // 替换题目区域的文本,旧题目会被新内容直接覆盖移除 questionArea.innerText = questionList[currentIndex] })
实际效果
- 页面刚打开时题目区域为空,第一次点击按钮就会加载第一道题
- 每点一次按钮就切换到下一道题,全程没有页面跳转,旧题目会被新内容完全替换,完全匹配核心交互需求
- 当所有题目展示完后,再点按钮会自动回到第一题,不需要额外加退出逻辑
内容的提问来源于stack exchange,提问作者Aspect
相关产品推荐
相关产品推荐

