iT邦幫忙

2021 iThome 鐵人賽

DAY 15
0
Modern Web

30天30個前端任務系列 第 15

#16. Quiz App(原生JS版)

#16. Quiz App

所謂Quiz App就是提供給用戶答題的小應用,包含數個選擇題,選完一個選項後會自動跳到下一道題目,最後顯示出有哪幾題答對。大家同樣可以在CodePen看一下成果。

實作邏輯
一開始是完成HTML結構與CSS切版,我們直接來看程式碼部分。

HTML

 <div class="quiz-container" id="quiz">
      <div class="quiz-header">
        <h2 id="question">Question text</h2>
        <ul>
          <li>
           <!-- 使用label for="a"的方式,讓input可選定的區塊包含到label部分-->
            <input type="radio" name="answer" id="a" class="answer">
            <label for="a" id="a_text">Question</label>
          </li>

          <li>
            <input type="radio" name="answer" id="b" class="answer">
            <label for="b" id="b_text">Question</label>
          </li>

          <li>
            <input type="radio" name="answer" id="c" class="answer">
            <label for="c" id="c_text">Question</label>
          </li>

          <li>
            <input type="radio" name="answer" id="d" class="answer">
            <label for="d" id="d_text">Question</label>
          </li>
        </ul>
      </div>
      <button id="submit">Submit</button>
    </div>

CSS部分沒有特別值得一提的,就先略過。

Javascript

// 建立種子資料
const quizData = [
  {
    question: 'Which language runs in a web browser?',
    a: 'Java',
    b: 'C',
    c: 'Python',
    d: 'JavaScript',
    correct: 'd',
  },
  {
    question: 'What does CSS stand for?',
    a: 'Central Style Sheets',
    b: 'Cascading Style Sheets',
    c: 'Cascading Simple Sheets',
    d: 'Cars SUVs Sailboats',
    correct: 'b',
  },
  {
    question: 'What does HTML stand for?',
    a: 'Hypertext Markup Language',
    b: 'Hypertext Markdown Language',
    c: 'Hyperloop Machine Language',
    d: 'Helicopters Terminals Motorboats Lamborginis',
    correct: 'a',
  },
  {
    question: 'What year was JavaScript launched?',
    a: '1996',
    b: '1995',
    c: '1994',
    d: 'none of the above',
    correct: 'b',
  },
]

const quiz = document.getElementById('quiz')
const answerEls = document.querySelectorAll('.answer')
const questionEl = document.getElementById('question')
const a_text = document.getElementById('a_text')
const b_text = document.getElementById('b_text')
const c_text = document.getElementById('c_text')
const d_text = document.getElementById('d_text')
const submitBtn = document.getElementById('submit')

// 預設要顯示的第一道題目,按照陣列長度的index為零
let currentQuiz = 0
// 得分數初始為零
let score = 0

// 將每個input的狀態設回未選定(false)
function deselectAnswers() {
  answerEls.forEach((answerEl) => (answerEl.checked = false))
}

function loadQuiz() {
  deselectAnswers()
  // 將quizData中的第一道題目,放進變數currentQuizData中,然後渲染到DOM.innerText裡面。
  const currentQuizData = quizData[currentQuiz]
  questionEl.innerText = currentQuizData.question
  a_text.innerText = currentQuizData.a
  b_text.innerText = currentQuizData.b
  c_text.innerText = currentQuizData.c
  d_text.innerText = currentQuizData.d
}

// 產生答案,視被選定的input.id為何(a, b, c, d)
function getSelected() {
  let answer

  answerEls.forEach((answerEl) => {
    if (answerEl.checked) {
      answer = answerEl.id
    }
  })

  return answer
}


submitBtn.addEventListener('click', () => {
  // 當submit被選中時,執行getSelected(),然後產生answer
  const answer = getSelected()

  if (answer) {
  // 若answer等於種子資料中的correct,則score + 1
    if (answer === quizData[currentQuiz].correct) {
      score++
    }
    
    // 被選定的題目序數 + 1
    currentQuiz++

    // 若被選定的題目序數小於題庫陣列長度,則再次渲染新的選擇題
    if (currentQuiz < quizData.length) {
      loadQuiz()
    } else {
    // 否則帶入成績
           quiz.innerHTML = `
              <h2>You answered ${score}/${quizData.length} questions correctly</h2>
              // 要重整畫面,一般會用onclick="location.reload()",但在CodePen環境會失效,因此改為 onclick="history.go(0)"
              // 兩者差別在於,前者是重新向server送request,後者是讀取緩存。
              <button onclick="history.go(0);">Reload</button>
          `
    }
  }
  
  loadQuiz()
  
})

今天同時在預備Vue版本的Quiz App,明天再跟各位分享!


上一篇
#15. CSS Perspective Slider(Vue版)
下一篇
#16. Quiz App(Vue版)
系列文
30天30個前端任務19

尚未有邦友留言

立即登入留言