为什么事件触发前我必须单击两次按钮?

时间:2020-06-26 08:17:08

标签: javascript class events addeventlistener

一个简单的选择题测验,有一个我无法解决的问题。首先,当我单击“下一个问题”按钮时,仅在第二次单击时显示下一个问题和答案时,才显示下一个问题和答案。 当我将runningQuestion ++放在问题上方时[runningQuestion] .displayAnswers() 就像我在nextQuestion函数中所做的一样,最初的问题已解决,但在要求您重试时出现在最后一个问题之后。当然,只有当您单击“立即重试”时,它才会跳过第一个问题。

class Question {
  constructor(question, answers, correct) {
    this.question = question;
    this.answers = answers;
    this.correct = correct;
  }

  displayAnswers() {
    document.querySelector('.question').innerHTML = `<div class="q1">${this.question}</div>`
    let i = 0
    let answers = this.answers
    for (let el of answers) {
      let html = `<div class="name" id=${i}>${el}</div>`
      document.querySelector('.answers').insertAdjacentHTML('beforeend', html)
      i++
    }
  }

}

const q1 = new Question('What\'s the capitol of Rwanda?', ['A: Dodoma', 'B: Acra', 'C: Kigali'], 2);
const q2 = new Question('What\'s is the square root of 0?', ["A: Not possible", 'B: 0', 'C: 1'], 1);
const q3 = new Question('Who was Rome\'s first emperor?', ['A: Tiberius', 'B: Augustus', 'C: Marcus Aurelius'], 1);

const questions = [q1, q2, q3];
let runningQuestion;
let gamePlaying;

init()

document.querySelector('.button1').addEventListener('click', nextQuestion)

function nextQuestion(e) {
  console.log(e.target)

  if (gamePlaying === true && runningQuestion <= questions.length - 1) {
    clearAnswers()
    document.querySelector('.button1').textContent = 'Next Question'
    runningQuestion++
    questions[runningQuestion].displayAnswers()
  }
  if (runningQuestion >= questions.length - 1) {
    document.querySelector('.button1').textContent = 'Try again!'
    runningQuestion = 0
  }
}

function clearAnswers() {
  document.querySelectorAll('.name').forEach(el => {
    el.remove()
  })

}

document.querySelector('.button2').addEventListener('click', resetGame)

function resetGame() {
  document.querySelector('.button1').textContent = 'Next Question'
  clearAnswers()
  runningQuestion = 0
  questions[runningQuestion].displayAnswers()
}

function init() {
  gamePlaying = true;
  runningQuestion = 0;
  questions[runningQuestion].displayAnswers()
}
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.container {
  display: flex;
  width: 400px;
  height: auto;
  margin: 100px auto;
  align-items: center;
  flex-direction: column;
}

.question {
  margin-top: 40px;
  color: rgb(102, 0, 0);
  font-size: 1.4rem;
}

.answers {
  display: flex;
  flex-direction: column;
  margin-top: 10px;
  height: 100px;
  margin-bottom: 15px;
}

.name {
  margin-top: 20px;
  cursor: pointer;
  color: rgb(102, 0, 0);
  font-size: 1.2rem;
}

.button1 {
  margin-top: 50px;
  border-style: none;
  width: 350px;
  height: 50px;
  font-size: 1.4rem;
}

ul>li {
  list-style-type: none;
  margin-top: 10px;
  font-size: 1.2rem;
  color: rgb(102, 0, 0);
  height: 30px;
  cursor: pointer;
  display: block;
}

.button2 {
  margin-top: 20px;
  border-style: none;
  width: 350px;
  height: 50px;
  font-size: 1.4rem;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
  <title>Quiz</title>
</head>

<body>
  <div class="container">
    <div class="question"></div>
    <div class="answers"></div>
    <button type="button" class="button1">Next Question</button>
    <button type="button" class="button2">Reset</button>
  </div>
  <script src="app.js"></script>
</body>

</html>

1 个答案:

答案 0 :(得分:1)

当前版本的问题是将runningQuestion重置为0,然后单击按钮时,执行nextQuestion,顾名思义,该行将下一个问题(runningQuestion++)。

我看到两种解决方法。通过将runningQuestion重置为-1使其进入0的两种“简便”方式:

class Question{constructor(e,s,t){this.question=e,this.answers=s,this.correct=t}displayAnswers(){document.querySelector(".question").innerHTML=`<div class="q1">${this.question}</div>`;let e=0,s=this.answers;for(let t of s){let s=`<div class="name" id=${e}>${t}</div>`;document.querySelector(".answers").insertAdjacentHTML("beforeend",s),e++}}}const q1=new Question("What's the capitol of Rwanda?",["A: Dodoma","B: Acra","C: Kigali"],2),q2=new Question("What's is the square root of 0?",["A: Not possible","B: 0","C: 1"],1),q3=new Question("Who was Rome's first emperor?",["A: Tiberius","B: Augustus","C: Marcus Aurelius"],1),questions=[q1,q2,q3];let runningQuestion,gamePlaying;init(),document.querySelector(".button1").addEventListener("click",nextQuestion);
/* Nothing changed above */

function nextQuestion(e) {
  runningQuestion++; // <---------------------------------------------------------

  if (gamePlaying === true && runningQuestion <= questions.length - 1) {
    clearAnswers();
    document.querySelector('.button1').textContent = 'Next Question';
    questions[runningQuestion].displayAnswers();
  }
  if (runningQuestion >= questions.length - 1) {
    document.querySelector('.button1').textContent = 'Try again!';
    runningQuestion = -1; // <-----------------------------------------------------
  }
}

/* Nothing changed below */
function clearAnswers(){document.querySelectorAll(".name").forEach(e=>{e.remove()})}function resetGame(){document.querySelector(".button1").textContent="Next Question",clearAnswers(),runningQuestion=0,questions[runningQuestion].displayAnswers()}function init(){gamePlaying=!0,runningQuestion=0,questions[runningQuestion].displayAnswers()}document.querySelector(".button2").addEventListener("click",resetGame);
/* Same CSS as yours */ *{box-sizing:border-box;margin:0;padding:0}.container{display:flex;width:400px;height:auto;margin:100px auto;align-items:center;flex-direction:column}.question{margin-top:40px;color:#600;font-size:1.4rem}.answers{display:flex;flex-direction:column;margin-top:10px;height:100px;margin-bottom:15px}.name{margin-top:20px;cursor:pointer;color:#600;font-size:1.2rem}.button1{margin-top:50px;border-style:none;width:350px;height:50px;font-size:1.4rem}ul>li{list-style-type:none;margin-top:10px;font-size:1.2rem;color:#600;height:30px;cursor:pointer;display:block}.button2{margin-top:20px;border-style:none;width:350px;height:50px;font-size:1.4rem}
<!-- Same HTML as yours --> <div class="container"> <div class="question"></div><div class="answers"></div><button type="button" class="button1">Next Question</button> <button type="button" class="button2">Reset</button></div>

或另一种方法,我发现它更清洁。当前代码可能会遇到的问题是,如果您需要跟踪其他事情(例如乐谱),例如,您可能会忘记在nextQuestion函数中重置它们。而且,如果您添加其他内容,则需要在代码中的多个位置进行重置。

我要做的就是简单地重用resetGame函数来重置所有内容:

class Question{constructor(e,s,t){this.question=e,this.answers=s,this.correct=t}displayAnswers(){document.querySelector(".question").innerHTML=`<div class="q1">${this.question}</div>`;let e=0,s=this.answers;for(let t of s){let s=`<div class="name" id=${e}>${t}</div>`;document.querySelector(".answers").insertAdjacentHTML("beforeend",s),e++}}}const q1=new Question("What's the capitol of Rwanda?",["A: Dodoma","B: Acra","C: Kigali"],2),q2=new Question("What's is the square root of 0?",["A: Not possible","B: 0","C: 1"],1),q3=new Question("Who was Rome's first emperor?",["A: Tiberius","B: Augustus","C: Marcus Aurelius"],1),questions=[q1,q2,q3];let runningQuestion,gamePlaying;
/* Nothing changed above */

const btn1 = document.querySelector('.button1');

init();

btn1.addEventListener("click", onButtonClick);

function isLastQuestion() { return runningQuestion >= questions.length - 1; }

function onButtonClick() {
  if (gamePlaying === true && !isLastQuestion()) {
    runningQuestion++;
    displayQuestion();
  } else {
    resetGame();
  }
}

function displayQuestion() {
    clearAnswers();
    btn1.textContent = isLastQuestion() ? 'Try again' : 'Next Question';
    questions[runningQuestion].displayAnswers();
}

/* Nothing changed below */
function clearAnswers(){document.querySelectorAll(".name").forEach(e=>{e.remove()})}function resetGame(){document.querySelector(".button1").textContent="Next Question",clearAnswers(),runningQuestion=0,questions[runningQuestion].displayAnswers()}function init(){gamePlaying=!0,runningQuestion=0,questions[runningQuestion].displayAnswers()}document.querySelector(".button2").addEventListener("click",resetGame);function init(){gamePlaying=true;runningQuestion = 0;questions[runningQuestion].displayAnswers()}
/* Same CSS as yours */ *{box-sizing:border-box;margin:0;padding:0}.container{display:flex;width:400px;height:auto;margin:100px auto;align-items:center;flex-direction:column}.question{margin-top:40px;color:#600;font-size:1.4rem}.answers{display:flex;flex-direction:column;margin-top:10px;height:100px;margin-bottom:15px}.name{margin-top:20px;cursor:pointer;color:#600;font-size:1.2rem}.button1{margin-top:50px;border-style:none;width:350px;height:50px;font-size:1.4rem}ul>li{list-style-type:none;margin-top:10px;font-size:1.2rem;color:#600;height:30px;cursor:pointer;display:block}.button2{margin-top:20px;border-style:none;width:350px;height:50px;font-size:1.4rem}
<!-- Same HTML as yours --> <div class="container"> <div class="question"></div><div class="answers"></div><button type="button" class="button1">Next Question</button> <button type="button" class="button2">Reset</button></div>