JS开发多选答题游戏 首题后得分每次累加2分而非1分问题排查
问题根本原因
计分翻倍是重复绑定点击事件监听器导致的:
- 每次调用
iterarJuego()渲染新题目时,都会执行内部的elegirRespuesta()方法 elegirRespuesta()的作用是给4个选项按钮绑定click事件,但DOM元素的事件监听器不会因为重复绑定被覆盖,新绑定的监听器会追加到执行队列里- 答第一题时每个选项仅绑定了1个监听器,点击后计分逻辑只执行1次,数值正常;答第二题时每个选项已经累计绑定了2个监听器,点击1次会触发2次计分逻辑,分数、答题数就会变成预期值的2倍,后续题目绑定的监听器会持续累加,数值偏差会越来越大。
修复方法
两种实现都可以解决问题,优先选第一种更简洁。
方法一:初始化时仅绑定一次事件(推荐)
事件绑定不需要跟着题目渲染重复执行,只需要页面首次加载时绑定一次即可:
- 删除
iterarJuego()函数中调用elegirRespuesta()的代码行 - 修改页面最末尾的初始化逻辑,先绑定事件再渲染第一题:
// 页面初始化 elegirRespuesta(); // 仅在页面加载时绑定一次点击事件 iterarJuego(); // 渲染第一道题目
方法二:每次绑定事件前清除旧监听器
如果要保留每次切题重新绑定事件的结构,在绑定新事件前清除之前绑定的监听器即可,修改elegirRespuesta代码如下:
// 抽离公共点击处理逻辑 function onOptionSelect(respuesta) { respSeleccionada = respuesta; funAnalizar(respSeleccionada); } function elegirRespuesta() { // 通过克隆节点的方式清除节点上所有已绑定的事件 [opcion1, opcion2, opcion3, opcion4].forEach((opcion, index) => { const nuevoNodo = opcion.cloneNode(true); opcion.replaceWith(nuevoNodo); // 更新节点引用 window[`opcion${index+1}`] = nuevoNodo; }); // 绑定新的点击事件 opcion1.addEventListener("click", () => onOptionSelect(arrayPreguntas[idPreg].opcionuno)); opcion2.addEventListener("click", () => onOptionSelect(arrayPreguntas[idPreg].opciondos)); opcion3.addEventListener("click", () => onOptionSelect(arrayPreguntas[idPreg].opciontres)); opcion4.addEventListener("click", () => onOptionSelect(arrayPreguntas[idPreg].opcioncuatro)); }
其他可优化的代码问题
document.querySelector('puntito1')选择器写法错误:如果是匹配class需要加前缀.,即document.querySelector('.puntito1');如果是匹配id需要加前缀#funAnalizar、respCorrecta、respIncorrecta三个函数定义了形参但函数内部没有使用,属于冗余代码,可以删除形参定义iterarJuego函数声明时没有定义入参,调用时传入idPreg属于无效传参,可以删掉调用时传入的参数opcion4.innerText = arrayPreguntas[idPreg].opcioncuatro;;行尾多写了一个分号,不影响运行但可以清理
内容的提问来源于stack exchange,提问作者Valentín Sanabria
相关产品推荐
相关产品推荐

