#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,明天再跟各位分享!


<<:  第十天:在 TeamCity 上完成第一个建置工作

>>:  卡夫卡的藏书阁【Book1】- 大纲和Kafka基础介绍

Day1 - 前言

杂谈 今年是个很特别的一年,对威尔猪来说也是,从没写过任何形式的笔记或文章,也没什麽特别规划,居然就...

【Day 07】- 第一只网路爬虫要用什麽函式库? (Requests)

前情提要 前一篇文章带大家看了chrome 开发工具的使用,并向下又说明了 Element 、Net...

予焦啦!附录:旅途拾贝

今天是 Hoddarla 系列文中的附录第 0 篇。笔者在这一年半的准备期当中送了两个 patch ...

Electron - 常用 API 解析

上一篇介绍了 Electron 的架构,今天来了解一下它到底有什麽 API 供我们使用~ (图片来源...

Alpine Linux Porting (一点八?)

开头先上图(?) [ 0.907920] Run /sbin/init as init proces...