You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现Trivia答题网页时出现索引翻倍而非递增1的问题排查

Trivia答题网页索引翻倍问题解决

问题描述

我要开发一个包含10道题的Trivia答题网页,从JSON文件读取题目数组,展示题目与选项,点击选项判断对错后计分并进入下一题。目前遇到的问题是索引(index)翻倍,只能展示第1、2、4、8题;尝试多种索引递增方式都无效,移除finishCheck中的loop()后索引可正常递增,添加额外事件监听也没效果。

相关代码

finishCheck() {
  this.index += 1;
  if (this.index < this.questions.length) {
    this.showQuestion();
    this.loop();
  } else {
    this.showScore();
    this.hideAnswers();
  }
}

loop() {
  const h = document.querySelectorAll(".btn-primary");
  h.forEach((o, i) => {
    o.innerHTML = this.questions[this.index].options[i].option;
    console.log(this.questions[this.index].options[i].option);
    o.addEventListener("click", () => {
      if (this.questions[this.index].options[i].isCorrect) {
        this.score++;
      }
      this.finishCheck();
    });
  });
}

问题原因

核心问题是重复绑定点击事件。每次调用loop()时,都会给所有.btn-primary按钮重新绑定一次click事件:

  • 第一次点击按钮,触发1次finishCheck(),index+1;
  • 第二次调用loop()时,又给按钮绑定了新的click事件,此时按钮上已有2个事件监听;
  • 第二次点击时会触发2次finishCheck(),index直接+2;
  • 第三次点击时按钮上已有4个事件监听,index+4,以此类推,就出现了1→2→4→8的跳跃。

解决方案

方案1:绑定新事件前移除旧事件

使用命名函数代替匿名函数,这样可以在绑定新事件前移除旧的事件监听:

finishCheck() {
  this.index += 1;
  if (this.index < this.questions.length) {
    this.showQuestion();
    this.loop();
  } else {
    this.showScore();
    this.hideAnswers();
  }
}

handleOptionClick(i) {
  if (this.questions[this.index].options[i].isCorrect) {
    this.score++;
  }
  this.finishCheck();
}

loop() {
  const buttons = document.querySelectorAll(".btn-primary");
  buttons.forEach((btn, i) => {
    btn.innerHTML = this.questions[this.index].options[i].option;
    // 先移除旧事件,再绑定新事件
    btn.removeEventListener("click", this.handleOptionClick.bind(this, i));
    btn.addEventListener("click", this.handleOptionClick.bind(this, i));
  });
}

方案2:仅绑定一次事件,动态更新选项

初始化时给按钮绑定一次事件,之后切换题目时只更新按钮文本,避免重复绑定:

constructor() {
  this.index = 0;
  this.score = 0;
  // 初始化时只绑定一次事件
  this.bindEventListeners();
  this.showQuestion();
  this.updateOptions();
}

bindEventListeners() {
  const buttons = document.querySelectorAll(".btn-primary");
  buttons.forEach((btn, i) => {
    btn.addEventListener("click", () => {
      if (this.questions[this.index].options[i].isCorrect) {
        this.score++;
      }
      this.finishCheck();
    });
  });
}

finishCheck() {
  this.index += 1;
  if (this.index < this.questions.length) {
    this.showQuestion();
    this.updateOptions(); // 只更新选项文本,不重新绑定事件
  } else {
    this.showScore();
    this.hideAnswers();
  }
}

updateOptions() {
  const buttons = document.querySelectorAll(".btn-primary");
  buttons.forEach((btn, i) => {
    btn.innerHTML = this.questions[this.index].options[i].option;
  });
}

方案3:使用事件委托

把事件绑定到按钮的父元素上,通过事件冒泡处理点击,只需要一次绑定:

constructor() {
  this.index = 0;
  this.score = 0;
  // 绑定事件到选项容器父元素
  document.querySelector(".options-container").addEventListener("click", (e) => {
    if (e.target.classList.contains("btn-primary")) {
      const buttonIndex = Array.from(document.querySelectorAll(".btn-primary")).indexOf(e.target);
      if (this.questions[this.index].options[buttonIndex].isCorrect) {
        this.score++;
      }
      this.finishCheck();
    }
  });
  this.showQuestion();
  this.updateOptions();
}

finishCheck() {
  this.index += 1;
  if (this.index < this.questions.length) {
    this.showQuestion();
    this.updateOptions();
  } else {
    this.showScore();
    this.hideAnswers();
  }
}

updateOptions() {
  const buttons = document.querySelectorAll(".btn-primary");
  buttons.forEach((btn, i) => {
    btn.innerHTML = this.questions[this.index].options[i].option;
  });
}

内容的提问来源于stack exchange,提问作者Jamie McGrath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 15:03:11