iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0

昨天已建立的 skills.vue 檔案,並做好上半部的 work experience 和 softskills,今天是 Skills Section 的第二部分 Hardskills 區塊,紀錄下我切版和建立元件的思考邏輯。

https://ithelp.ithome.com.tw/upload/images/20250921/20178581O7zpMMCppu.png

HardSkills 的卡片結構高度相似

  • 每張卡片都有「分類標題」
  • 一段技能說明文字
  • 多個簡潔技能標籤

因此,可以將卡片抽象化,建立一個 HardSkillCard 元件,並讓父元件(skills.vue)只需透過傳遞資料(props)告訴子元件「標題、說明、技能列表」即可。再利用v-for 迴圈渲染,一次生成多張結構相同但內容不同的卡片。


什麼時候可以建立成元件?

剛開始在在設計程式碼架構時,很常會有這個疑問。通常一個區塊在 3 個以上的地方出現,或結構高度相似需要複製貼上時,就會將區塊抽出建立成子元件,方便程式碼的後續維護。

這樣的做法有幾個優點:

  1. 程式碼更乾淨 → 結構定義在元件裡,父層只管理資料。
  2. 維護性高 → 如果未來想改設計(例如加 icon、調整樣式),只要修改元件一次就能套用到全部。
  3. 可擴充性 → 只要新增資料就可以自動產生,無需重寫排版。

在進行設計時,也能以這些判斷基準,來決定是否建立元件。


父元件和子元件之間的傳遞

  • 父組件:大頁的那個 (skills.vue)
  • 子組件:小的那個,被包的那個 (hardskills-card.vue)

父/子元件之間的數據流傳遞,是運用 propsemit 來運作的,分別的傳遞的方向如下:
https://ithelp.ithome.com.tw/upload/images/20250921/20178581aJcO2nCyXO.png

  • props:父組件向子組件傳遞數據,使用 :propName 綁定
    https://ithelp.ithome.com.tw/upload/images/20250921/20178581O8TKsBY3od.png
  • emit:子組件向父組件傳遞事件和數據,使用 emit(’emitEventName’, data)
    https://ithelp.ithome.com.tw/upload/images/20250921/20178581qzv5zSdV1L.png

在這邊的實例是:

  • 父元件:負責引入 <HardSkillsCard />,並定義每張卡片的內容(如標題、說明、技能標籤)。
  • 資料傳遞:父元件將卡片內容作為 props 傳入子元件,確保結構與資料分離。
  • 子元件:在 hardskills-card.vue 內接收 props,並將資料渲染到對應區塊(標題、說明、技能列表)。
  • 注意:propsName 要取名的一樣,不然抓不到
// skills/skills.vue (父元件)

<template>
	<v-row class="d-flex w-100" align="stretch">
	    <v-col 
	        cols="12" sm="4" md="4" lg="4"
	        v-for="value in hardskills" :key="value.category" 
	        class="d-flex"
	    >
	        <HardskillsCard :hardskills="value"/>
	    </v-col>
	</v-row>
</template>

<script setup>
import HardskillsCard from './hardskills-card.vue';

// 這邊會傳進去子元件中
const hardskills = ref([
  {
    category: '分類1',
    description: '說明說明說明',
    skills: ['Adobe Illustrator', 'Canva'],
  },
  {
    category: '分類2',
    description: '說明說明說明',
    skills: ['Flow Chart', 'Wireframe', 'Prototype'],
  },
  {
    category: '前端技術',
    description: '說明說明說明',
    skills: ['React', 'Vue', 'Git'],
  },
]);
</script>
// skills/hardskills-card.vue (子元件)

<template>
    <div class="bg-white pa-8 custom-rounded-md d-flex flex-column"
        :class="isDesktop ? 'mt-6': 'mt-3'">
        <div class="d-flex flex-row">
            <div style="border: 7px solid #BF6730;"/>
            <div class="text-h3-semi-bold text-brown ml-4">
                {{ hardskills.category }}
            </div>
        </div>
        <div class="text-h4-regular text-brown mt-4 **flex-grow-1**">
            {{ hardskills.description }}
        </div>
        <div 
            v-for="value in props.hardskills.skills"
            class="text-h4-semi-bold text-orange">
            # {{ value }}
        </div>
    </div>
</template>

<script setup>
const props = defineProps({
  hardskills: {
    type: Object,
    required: true,
    default: () => {},
  }
});
</script>

這邊的內容區塊也需注意保持相同高度,讓視覺平衡一些。先讓最外層填滿高度,內層 div 需要一起延伸拉長的加上 flex-grow-1
https://ithelp.ithome.com.tw/upload/images/20250921/20178581RRY5ErCpev.png

哎呀,又是細節滿滿的一天!但挺好的,終於整理出 props 和 emit 的作用!呼!


上一篇
Day 7 Skills section 1 - 技能分類帽
系列文
《運用通勤時間打造線上履歷作品集:30 天 Nuxt 自我挑戰》8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言