iT邦幫忙

2025 iThome 鐵人賽

DAY 30
0
Vue.js

新手學習Vue.js與實作之旅系列 第 30

Day30 實作 Quiz (III)

  • 分享至 

  • xImage
  •  

今天的內容將延續昨天的實作內容,繼續探討 Vue 實際的應用/images/emoticon/emoticon37.gif
以下實作是使用 Composition API 撰寫,將著重講解<script setup>標籤的程式碼,以及<template>標籤內有使用到 Vue 語法的地方:

5.點擊題目的選項 (跳下一題/紀錄答對題數)

  • emit
    • 在子元件 Question.vue 可以透過使用 defineEmits() 來定義要觸發的事件, defineEmits(["selectOption"]) 表示 Question 元件會對外發送 selectOption 事件。
    • 在 emitSelectOption 方法中呼叫 emit("selectOption", isCorrect),表示將 isCorrect 這個資料傳給父元件 QuizView.vue 。
  • 事件處理 v-on (簡寫為 @ )
    將題目的選項加上事件監聽 @click="emitSelectOption(option.isCorrect)",當選項被點擊時,會執行 emitSelectOption 的方法。
<!-- Question.vue 檔案 -->
<script setup>
    import {defineEmits} from "vue"

    const emit = defineEmits(["selectOption"])
    const emitSelectOption = (isCorrect) => {
        emit("selectOption", isCorrect)
    }
</script>
<template>
    <div class="options-container">
        <div 
            v-for="option in question.options" 
            :key="option.id"
            @click="emitSelectOption(option.isCorrect)"
            class="option">
            <p class="option-label">{{ option.label }}</p>
            <div class="option-value">
                <p>{{ option.text }}</p>
            </div>
        </div>
    </div>
</template>
  • ref
    透過使用 const numberOfCorrectAnswers = ref(0) 建立一個響應式變數,Vue 會自動追蹤它的變化並更新畫面。
  • 事件處理 v-on (簡寫為 @ )
    父元件 QuizView.vue 透過使用 @selectOption="onOptionSelected" 監聽子元件的事件,當子元件發出 emit("selectOption", isCorrect) 時,就會觸發 onOptionSelected 方法。
<!-- QuizView.vue 檔案 -->
<script setup>
    import  quizes from "../data/quizes.json"
    import Question from "../components/Question.vue"
    const numberOfCorrectAnswers = ref(0)
    const onOptionSelected = (isCorrect) => {
        if(isCorrect){
            numberOfCorrectAnswers.value++
        }
        currentQuestionIndex.value++
    }
</script>
<template>
    <div>
        <div>
            <Question 
            v-if="!showResults"
            :question="quiz.questions[currentQuestionIndex]"
            @selectOption="onOptionSelected"
            />   
        </div>
    </div>
</template>

6.答題結果畫面 (題數和進度條不超過總題數)

  • Props

動態Props:使用 v-bind (或簡寫:) 的方式將外層元件的資料內容傳入

表示 Result 元件會從父元件 (QuizView.vue) 接收題目總數和答對數並顯示在畫面上。

  • RouterLink
    透過使用 RouterLink 產生可點擊的路由連結,讓使用者可以回到首頁 (QuizesView.vue)。
<!-- Result.vue 檔案 -->
<script setup>
    import { defineProps } from 'vue';
    import { RouterLink } from 'vue-router'; 

    const {quizQuestionLength, numberOfCorrectAnswers} = defineProps(["quizQuestionLength", 
    "numberOfCorrectAnswers"])
</script>
<template>
    <div class="result">
        <p>Your Results...</p>
        <h1>{{ numberOfCorrectAnswers }}/{{ quizQuestionLength }}</h1>
        <RouterLink to="/">Go Back</RouterLink>
    </div>
  • 條件渲染 v-if
    透過使用 v-if 和 v-else 控制結果畫面是否顯示,當 showResults 為 false 顯示題目畫面, true 才會顯示結果畫面。
<!-- QuizView.vue 檔案 -->
<script setup>
    import {useRoute} from "vue-router"
    import  quizes from "../data/quizes.json"
    import Result from "../components/Result.vue"

    const route = useRoute()
    const quizId = parseInt(route.params.id)
    const quiz = quizes.find(q => q.id === quizId)
    const currentQuestionIndex = ref(0)
   

    const numberOfCorrectAnswers = ref(0)
    const onOptionSelected = (isCorrect) => {
        if(isCorrect){
            numberOfCorrectAnswers.value++
        }
        if(quiz.questions.length-1 === currentQuestionIndex.value){
            showResults.value = true
        }
        currentQuestionIndex.value++
    }

    const showResults = ref(false)

</script>

<template>
    <div>
        <div>
            <Question 
            v-if="!showResults"
            :question="quiz.questions[currentQuestionIndex]"
            @selectOption="onOptionSelected"
            />
            <Result 
                v-else
                :quizQuestionLength="quiz.questions.length"
                :numberOfCorrectAnswers="numberOfCorrectAnswers"
            />
        </div>
    </div>
</template>

參考資源

https://www.youtube.com/watch?v=I_xLMmNeLDY


上一篇
Day29 實作 Quiz (II)
系列文
新手學習Vue.js與實作之旅30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言