在昨天的探索中,我們得知我們的需求「銷售系統」是基於 HTML、CSS 和 JavaScript 的靜態原型(prototype)。每個頁面都是一個獨立的 HTML 檔案,例如 index.html
(登入頁)、dashboard.html
(主畫面)、order-management.html
(訂單管理) 等。
這邊起初只是為了可以快速 Demo 並確認需求的 prototype 所以透過 AI 產出了一份原始碼,讓我們能夠快速地看到一個可操作的介面,並與團隊進行溝通。
實際上, 原型 (Prototype) 和 產品 (Production) 之間存在著一段非常大的距離。
這份由 AI 產出的程式碼,雖然能動,但若要將其作為一個可長期維護的「產品」,它的架構存在著一些問題,因此,我們將以 Vue 為核心進行重構,目標是建立一個可維護、可擴展的全新基礎。
讓我們來看看以下這幾個頁面的程式碼
幾乎每個頁面都有一個結構相似的 header,用來顯示當前頁面的標題,但它們是在每個檔案中寫死的。
dashboard.html
的標題:
<header>
<h1>銷售系統儀表板</h1>
</header>
order-management.html
的標題:
<header>
<h1>訂單管理</h1>
<a href="dashboard.html" class="back-button">返回主頁</a>
</header>
customer-management.html
的標題:
<header>
<h1>客戶管理</h1>
<a href="dashboard.html" class="back-button">返回主頁</a>
</header>
inventory-query.html
的標題:
<header>
<h1>庫存查詢</h1>
<a href="dashboard.html" class="back-button">返回主頁</a>
</header>
這樣子會有幾個問題:
dashboard.html
的 header 就沒有「返回主頁」按鈕,這種差異導致每個 header 都得客製化。讓我們接著再看看 dashboard.html
和 order-management.html
的一小部分程式碼片段:
dashboard.html
的按鈕:
<a href="order-management.html" class="dashboard-button">
<i class="fas fa-file-alt"></i>
<span>訂單管理</span>
</a>
order-management.html
的返回按鈕:
<a href="dashboard.html" class="back-button">返回主頁</a>
從這邊可以發現,即使是功能單純的「按鈕」,在不同頁面中也有著不同的寫法和樣式。隨著系統功能越來越複雜,這種寫法將會導致以下問題:
為了解決以上問題,我們可以使用 Vue 的核心思想:元件化 (Component-based Architecture)。
在 Vue 中,我們可以將一個複雜的頁面,拆分成一個個獨立、可重複使用的 元件 (Component)。每個元件都包含自己的 HTML 模板、CSS 樣式和 JavaScript 邏輯。
這種架構的優點顯而易見:
現在,讓我們來實際規劃如何將現有的 POS 系統拆分成 Vue Component。
我們可以從現有的 HTML 中找出以下可複用的 UI Component:
BaseButton.vue
:所有可點擊的按鈕,例如「登入」、「返回主頁」、「查看詳情」等。我們可以透過 props
來控制它的文字、樣式和行為。PageHeader.vue
:每個頁面的標題列。我們可以透過 prop
傳入標題文字。BaseCard.vue
:在Dashboard中,每個功能的 entry point 都是一張卡片。這個元件包含圖示、標題和連結。OrderSearchForm.vue
:處理所有跟「搜尋」相關的邏輯,例如:管理輸入框的狀態、處理搜尋按鈕的點擊事件、驗證輸入內容等。BaseInput.vue
/ Select.vue
:表單中的輸入框和下拉選單,可以封裝成獨立的元件以方便管理表單狀態。BaseTable.vue
:訂單管理頁面中的表格。我們可以將表頭和資料作為 props
傳入,讓它動態生成表格。在 Vue 中,應用程式是由一個個元件組成的樹狀結構。我們的 POS 系統可以被設計成如下的結構:
App.vue
:根元件,作為整個應用程式的容器。它將包含路由視圖 (<router-view>
),用來顯示不同頁面的內容。
頁面元件 (Page Components):每個 HTML 檔案都將轉化為一個頁面元件。
Login.vue
Dashboard.vue
OrderManagement.vue
基礎 UI 元件 (UI Components):我們剛剛找出的可複用元件。
讓我們以「 index.html(登入頁)
」為例,看看它的元件樹會長什麼樣子:
Login.vue (登入頁面本身)
└── div.login-card (主要的卡片容器)
│
├── div.login-header (包含 Logo 和標題)
│
├── BaseSelect.vue (用於選擇門市)
│
├── BaseButton.vue (用於 Google 登入)
│
├── BaseButton.vue (用於 LINE 登入)
│
└── div.login-footer (底部的說明文字)
看到這裡,你可能會問一個問題:『為什麼 div.login-card 和 div.login-header ... 還是 div,沒有被建立成元件呢?』
這是一個非常好的問題,我們可以透過幾個簡單的原則來判斷:
重複性 ( Is it Reusable? ) : 是否會在專案的多個地方被使用?
複雜性 ( Is it Complex? ) : 是否包含自己獨立的、複雜的資料或使用者互動邏輯?
可測試性 ( Is it Testable? ) : 是否需要獨立測試?
元件化的目標是化繁為簡。當你發現建立一個元件所帶來的成本,超過它所需要解決的問題時,那可能就是一種 『過度設計』 。
透過這樣的設計,Login.vue
頁面本身變得非常簡潔,它只負責組合各個子元件,而不關注每個按鈕或表格的具體實現細節。
今天,我們完成了從 Prototype 到 Component 的思維轉換,並為我們的銷售系統設計了一個清晰的 Vue 元件架構。
今日重點回顧:
明天,我們將繼續深入Vueの呼吸・貳之型,探討在 Vue 中如何管理我們的資料流,猪突猛進!!