今天的內容將延續昨天的實作內容,繼續探討 Vue 實際的應用
以下實作是使用 Composition API 撰寫,將著重講解<script setup>
標籤的程式碼,以及<template>
標籤內有使用到 Vue 語法的地方:
<!-- Card.vue 檔案 -->
<script setup>
import { defineProps } from 'vue'
import {useRouter} from "vue-router"
const {quiz} = defineProps(['quiz'])
const router = useRouter()
const navigateToQuiz = () => {
router.push(`/quiz/${quiz.id}`)
}
</script>
<template>
<div class="card" @click="navigateToQuiz">
<img :src="quiz.img" alt="">
<div class="card-text">
<h2>{{ quiz.name }}</h2>
<p>{{ quiz.questions.length }} questions</p>
</div>
</div>
</template>
創建 QuizView.vue 檔案並寫入題目內容,然後在 index.js 寫入 QuizView 的路由規則。
// index.js 檔案
import { createRouter, createWebHistory} from "vue-router"
import QuizesView from "../views/QuizesView.vue"
import QuizView from "../views/QuizView.vue"
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path:"/",
name:'quizes',
component: QuizesView
},
{
path:"/quiz/:id",
name:"quiz",
component: QuizView
}
]
})
export default router
動態Props:使用 v-bind (或簡寫:) 的方式將外層元件的資料內容傳入
將 QuizView.vue 的題目程式碼劃分到 Question.vue 和 QuizHeader.vue 檔案中,透過隔離程式碼,以便於修改程式碼、增加重複使用性。
<!-- QuizView.vue 檔案 -->
<script setup>
import Question from "../components/Question.vue"
import QuizHeader from "../components/QuizHeader.vue"
import {useRoute} from "vue-router"
import {ref, computed} from "vue"
import quizes from "../data/quizes.json"
const route = useRoute()
const quizId = parseInt(route.params.id)
const quiz = quizes.find(q => q.id === quizId)
const currentQuestionIndex = ref(0)
const questionStatus = computed(() =>
`${currentQuestionIndex.value}/${quiz.questions.length}`)
const barPercentage = computed(() =>
`${currentQuestionIndex.value/quiz.questions.length*100}%`)
</script>
<template>
<div>
<QuizHeader
:questionStatus="questionStatus"
:barPercentage="barPercentage"
/>
<div>
<Question
:question="quiz.questions[currentQuestionIndex]"
/>
</div>
</div>
</template>
<!-- Question.vue 檔案 -->
<script setup>
import {defineProps} from "vue"
const {question} = defineProps(['question'])
</script>
<template>
<div class="question-container">
<h1 class="question">
{{ question.text }}
</h1>
</div>
<div class="options-container">
<div
v-for="option in question.options"
:key="option.id"
class="option">
<p class="option-label">{{ option.label }}</p>
<div class="option-value">
<p>{{ option.text }}</p>
</div>
</div>
</div>
</template>
<!-- QuizHeader.vue 檔案 -->
<script setup>
import { defineProps } from 'vue'
const {questionStatus, barPercentage} =
defineProps (["questionStatus","barPercentage"])
</script>
<template>
<div>
<header>
<h4>Question {{ questionStatus }}</h4>
<div class="bar">
<div class="completion" :style="{ width: barPercentage }"></div>
</div>
</header>
</div>
</template>
<style scoped>
header{
margin-top: 20px;
}
header h4{
font-size: 30px;
}
.bar{
width: 300px;
height: 50px;
border: 3px solid rgb(40, 126, 28);
}
.completion{
height: 100%;
width: 0%;
background-color: rgb(97, 167, 98);
}
</style>
https://www.youtube.com/watch?v=I_xLMmNeLDY