iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0
Vue.js

需求至上的 Vue 魔法之旅系列 第 8

Chapter 2:前端架構升級 – 元件化與資料流拓展

  • 分享至 

  • xImage
  •  

前言|從需求出發的升級理由

在完成 在 Chapter 1 中,我們靠需求驅動,一步步寫出一支可完整點單、送單、統計的應用。但隨著功能增加,單一檔案的程式碼開始膨脹:

  • 修改一小段功能就得翻找整份檔案

  • 不同區塊邏輯彼此糾纏,維護困難

這正是推導出「組件化」的最佳時機:

我們不是因為大家都說: 一定要學組件化才去study去學,而是因為實際需求與痛點驅使

為什麼會這樣說?

在大型的應用程式當中,需要將表單、清單、統計等拆成可重複利用可獨立維護的元件否則你一直重複寫同樣的按鈕或是彈跳視窗不是會很幹XDD!!/images/emoticon/emoticon01.gif

然而,想要邁向更大型、更維護良好的專案,需要 元件化拆分、API 串接、狀態管理 與 表單驗證 等更進階的工程能力。

本章將從「如何拆分元件」開始,一步步帶大家完成更結構化的 Vue 應用,並建立與後端溝通與可維護的資料流。

我們chapter2系列的內容是這樣

基本上還是會因為需求驅動來學習這些咚咚~

Day 標題 核心學習內容
Day 7 如何把複雜的咒語變簡單:組件化設計 將龐大的 App.vue 拆成 OrderForm(下單表單)、OrderList(訂單清單)、OrderStats(統計表)三大元件。學會 Props / Emit 的父子元件溝通,理解組件化帶來的維護性與重複利用價值。
Day 8 讓你接受我的控制:受控表單設計 受控元件 管理輸入狀態,示範重置、暫存、回填等功能,優化表單 UX
Day 9 連接世界的魔法:API 溝通術 介紹 fetch / axiosService 層封裝,學習處理 loadingerror 狀態,打通與後端溝通的資料管道。
Day 10 立即小助手:v-watch 使用 watch 監聽資料變化,動態更新甜度、冰量等客製化選單;並討論 快取策略效能優化
Day 11 中央魔島書院:共享的 store Pinia store 集中管理訂單狀態,示範跨頁面共享資料與 模組化維護 的做法。
Day 12 可靠的中央行政單位:getter / setter 把 Day 5 的統計邏輯重構到 Pinia getters,集中衍生資料與計算,降低元件負擔。
Day 13 驗證自己的咒語語法:表單與資料驗證 使用 VeeValidate + Yup 完成 必填格式檢查 與即時提示,確保輸入資料的正確與安全。

我們第二章的章節會照這樣的學習路徑執行
https://ithelp.ithome.com.tw/upload/images/20250922/20121052AIdCi1Ruhk.png

一、前導思維(為什麼拆組件)

1.拆解需求

凡是從觀察跟需求開始

我們觀察 Day1~Day5 的畫面:飲料 / 甜度 / 冰量 這三塊 UI其實是同一種結構,只是標題與選項文案不同。

https://ithelp.ithome.com.tw/upload/images/20250922/20121052gvEzAKkCmJ.png

與其在頁面上複製三份幾乎一樣的 HTML,不如抽出一個通用組件(OptionGroup):

  • 傳入 legend(群組標題)

  • 傳入 options(選項陣列)

今天先做純展示版(stateless / presentational):

不含 v-model / @change / Pinia

只渲染三組清單,為 Day7 的「組件化 + 互動」打地基

2.設計程式的flow

今天我們算是前導篇章

所以程式flow比較簡單,只是要把組件的概念具象化

所以流程是長這樣
https://ithelp.ithome.com.tw/upload/images/20250922/20121052sqCsZeal1P.png

3. Vue對應的技術

3.1 屬性傳遞

props 是子元件的接收參數。父元件可將資料以屬性方式傳入,子元件透過 defineProps 宣告要接收哪些資料

其實可以不用想這麼複雜,你就想這邊的子組件是誰? 就是我們需要重複利用的OptionGroup.vue

例如我們要傳飲料的屬性傳下去

先在父祖件引入oprtiongroup,這時候就可以直接使用 組件

那麼其中的屬性跟標籤就可以透過綁定屬性來傳下去

在父祖件中我可以把drink的state綁起來傳下去,這個叫做option(飲料的選項)


<!-- 父元件 App.vue -->
<OptionGroup :options="drinks" legend="選擇飲料" />

在子組件中,我可以透過defineprops定義物件結構

把要接受父親的屬性型別定義出來(比如說我們飲料有紅茶跟綠茶陣列)


<!-- 子元件 OptionGroup.vue -->
<script setup>
const props = defineProps({
  legend: String,
  options: Array
})
</script>

3.2.資料流思考

在父祖件中

我們所需要的資料

const drinks     = ['紅茶', '綠茶']
const sweetness  = ['正常甜', '去糖']
const iceLevels  = ['正常冰', '去冰']

在template中,我們引入Optiongroup就可以重複利用這個組件

<OptionGroup legend="步驟 1:選擇飲料" :options="drinks" />
<OptionGroup legend="步驟 2:選擇甜度" :options="sweetness" />
<OptionGroup legend="步驟 3:選擇冰量" :options="iceLevels" />

在子祖件中

這樣我們就可以接收
上面飲料的選項/甜度冰量等客製化了

<script setup>
const props = defineProps({
  legend: String,
  options: Array
})
</script>

<template>
  <fieldset>
    <legend>{{ props.legend }}</legend>
    <ul>
      <li v-for="opt in props.options" :key="opt">{{ opt }}</li>
    </ul>
  </fieldset>
</template>

4. 程式碼實作

我們把今天的程式碼結合就可以變成

父組件

<!-- App.vue -->
<script setup>
import OptionGroup from './OptionGroup.vue'

const drinks     = ['紅茶', '綠茶']
const sweetness  = ['正常甜', '去糖']
const iceLevels  = ['正常冰', '去冰']
</script>

<template>
  <h2>Chapter 2:組件化暖身(純展示)</h2>

  <!-- 三個清單:今天只做 UI 呈現,不處理狀態與事件 -->
  <OptionGroup legend="步驟 1:選擇飲料"  :options="drinks"    name="drink-demo" />
  <OptionGroup legend="步驟 2:選擇甜度"  :options="sweetness" name="sweet-demo" />
  <OptionGroup legend="步驟 3:選擇冰量"  :options="iceLevels" name="ice-demo" />
</template>

子組件

<!-- OptionGroup.vue -->
<script setup>
const props = defineProps({
  legend: { type: String, required: true },
  options: { type: Array, required: true }, // 例:['紅茶', '綠茶']
  name:   { type: String, required: true }, // for radio 的群組名(純展示可用或忽略)
})
</script>

<template>
  <fieldset>
    <legend class="title">{{ legend }}</legend>
    <ul class="list">
      <li v-for="opt in options" :key="opt" class="item">
        <label><input type="radio" :name="name" :value="opt" disabled /> {{ opt }}</label>
      </li>
    </ul>
  </fieldset>
</template>


可以從這邊試玩
Chapter2 的組件前導

結果:父元件的 drinks / sweetness / iceLevels 陣列,就會經由 props 傳到 OptionGroup,由子元件渲染出完整的選單 UI。

今天我們可以先有一點概念,明天就會開始正式拆解我們的組件瞜~!!


上一篇
Day 6:從實習魔法師到大魔法師,不被AI取代的關鍵(更進化的思考學習到的東西)
系列文
需求至上的 Vue 魔法之旅8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言