iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0
Vue.js

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

Day28 實作 Quiz (I)

  • 分享至 

  • xImage
  •  

今天的內容將透過實作,複習先前學習的 Vue 語法以及 Vue Router/images/emoticon/emoticon07.gif
以下實作是使用 Composition API 撰寫,將著重講解<script setup>標籤的程式碼,以及<template>標籤內有使用到 Vue 語法的地方:

1.主畫面呈現

在 src 創建 data 資料夾,在 data 資料夾創建 quizes.json 檔案,寫入 quiz 的題目、選項與答案,並在 App.vue 檔案匯入此 json 檔案。

  • 列表渲染 v-for
    透過遍歷來渲染所有 quiz 圖卡,並且搭配 key 屬性當作唯一識別碼。
  • 屬性綁定 v-bind (簡寫為 :)
    • 透過 key 屬性綁定 quiz.id 作為 quiz 的唯一識別碼,讓 Vue 能夠高效追蹤每個 quiz 圖卡
    • 透過 src 屬性來動態設定 quiz 的圖卡背景,將每個 quiz 的圖片套用到對應的 DOM 元素上。
  • 插植表達式 {{ }}
    透過使用插植表達式來渲染各個 quiz 圖卡上的文字
<div v-for="quiz in quizes" :key="quiz.id" class="card">
    <img :src="quiz.img" alt="">
    <div class="card-text">
        <h2>{{ quiz.name }}</h2>
        <p>{{ quiz.questions.length }}</p>
    </div>   
</div>

2.搜尋功能

  • 雙向綁定 v-model
    將文字輸入區域和搜尋內容區域綁定,並且透過 .trim 修飾符會去除輸入內容前後的空白,可以防止使用者輸入無效的空格。
<input v-model.trim="search" type="text" placeholder="Search...">
  • 監聽器 Watchers
    watch 會監聽一個響應式變數 search ,當 search 的值發生變化時,就會觸發裡面的函式,在 quiz 清單中利用 filter 方法篩選出名稱符合搜尋條件的項目,使畫面上的 quiz 圖卡能夠即時更新,達到搜尋過濾的效果。
<script setup>
    import q from "../data/quizes.json"
    import {ref, watch} from "vue"

    const quizes = ref(q)
    const search = ref("")
    watch(search, () => {
        quizes.value = q.filter(quiz =>
        quiz.name.toLowerCase().includes(search.value.toLowerCase()))
    })
</script>
  • Props

Props 傳遞資料的方式可以分成兩種:
靜態Props:直接傳入字串而不是外層元件的資料內容。
動態Props:使用 v-bind (或簡寫:) 的方式將外層元件的資料內容傳入。

將 App.vue 的 card 程式碼劃分到 Card.vue 檔案中,透過隔離程式碼,以便於修改程式碼、增加重複使用性。

<!-- App.vue 檔案 -->
<script setup>
    import q from "../data/quizes.json"
    import {ref, watch} from "vue"
    import Card from "../components/Card.vue"
    
    const quizes = ref(q)
    const search = ref("")
    watch(search, () => {
        quizes.value = q.filter(quiz => 
        quiz.name.toLowerCase().includes(search.value.toLowerCase()))
})
</script>

<template>
    <div>
        <header>
            <h1>Quizes</h1>
            <input v-model.trim="search" type="text" placeholder="Search...">
        </header>
        <div class="options-container">
            <Card  v-for="quiz in quizes" :key="quiz.id" :quiz="quiz"/>
            <!-- App.vue 的 card 程式碼部分: -->
            <!-- <div v-for="quiz in quizes" :key="quiz.id" class="card">
                <img :src="quiz.img" alt="">
                <div class="card-text">
                    <h2>{{ quiz.name }}</h2>
                    <p>{{ quiz.questions.length }}questions</p>
                </div>   
            </div> -->
        </div>
  </div>
</template>
<!-- Card.vue 檔案 -->
<script setup>
    import { defineProps } from 'vue'  
    const {quiz} = defineProps(['quiz'])
</script>

<template>
    <div class="card">
        <img :src="quiz.img" alt="">
        <div class="card-text">
            <h2>{{ quiz.name }}</h2>
            <p>{{ quiz.questions.length }}questions</p>
        </div>   
    </div>
</template>

參考資源

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


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

尚未有邦友留言

立即登入留言