~/blog/laravel-blade-component-advanced-patterns-2026.md
Laravel 與後端開發 · 2026 / 02 / 18

Blade Component 進階封裝術:Laravel 13 從原子設計到效能優化

Eric — 浪花科技創辦人 / AI 架構師
Eric
浪花科技創辦人 · AI 架構師
Blade Component 進階封裝術:Laravel 13 從原子設計到效能優化
目錄 table-of-contents.md

View 層的整潔度,往往決定一個 Laravel 專案三年後是資產還是負債。這篇要分享我在 Laravel 13 用 Blade Component 做進階封裝的完整心法:從原子設計的元件拆分原則,到屬性傳遞與渲染效能優化,把髒亂的 View 層一步步收乾淨。

最近我接手了一個號稱「傳家寶」等級的舊 Laravel 專案,打開 resources/views 資料夾的那一刻,我彷彿看到了義大利麵工廠發生粉塵爆炸——滿地的 @php 邏輯區塊、無限巢狀的 @if、還有那種複製貼上了五十次的 Modal 視窗程式碼。這種「義大利麵程式碼」(Spaghetti Code)不只在 Controller 發生,View 層往往才是技術債最深重的災區。

到了 2026 年,Laravel 已經進化到第 13 版(或更先進的迭代),Blade 模板引擎早已不再只是單純的 HTML 替換工具。如果你還在用傳統的 @include 或是把 Eloquent Model 直接丟進 View 裡面跑迴圈,那你可能正在扼殺專案的可維護性。

今天這篇文章,我們不談基礎語法,要談的是「架構級」的 Blade 最佳實務。我們將結合原子設計(Atomic Design)概念與最新的 Component 特性,教你如何把 View 層整理得像樂高積木一樣乾淨、好維護。

1. 拋棄 @include,擁抱 Component 體系

雖然 @include 依然存在,但在 2026 年的現代化開發中,它應該被視為「次等公民」。為什麼?因為 @include 無法強制規範傳入的數據型別,也難以封裝獨立的邏輯。相比之下,Blade Components(尤其是 Anonymous Components 和 Class-based Components)提供了更強大的封裝能力。

為什麼 Component 完勝?

  • 屬性隔離(Attribute Bag): 自動處理 HTML 屬性合併,不用手動寫 class 拼接邏輯。
  • Slots(插槽): 讓結構更靈活,不再是死板的參數傳遞。
  • 強型別支援: 在 Class-based Component 中,你可以利用 PHP 的型別系統來驗證傳入 View 的資料。

❌ 過時的寫法 (@include):

<!-- 難以維護,變數來源不明 -->
@include('partials.button', ['type' => 'submit', 'class' => 'btn-primary', 'text' => '送出'])

✅ 2026 推薦寫法 (Component):

<!-- 語意清晰,屬性自動合併 -->
<x-ui.button type="submit" variant="primary">
    <x-icon.send class="w-4 h-4 mr-2" />
    送出表單
</x-ui.button>

2. 引入原子設計 (Atomic Design) 到 Blade 目錄結構

工程師最頭痛的就是「命名」與「檔案歸檔」。在大型專案中,我強烈建議依照原子設計的方法論來組織你的 resources/views/components 目錄。這能讓新進的工程師(或是三個月後的你自己)不用通靈就能找到檔案。

建議的目錄結構:

  • Atoms (原子): 不可再分割的最小單位。例如:按鈕 (Button)、輸入框 (Input)、標籤 (Label)、圖標 (Icon)。
  • Molecules (分子): 由原子組成的簡單群組。例如:搜尋列 (SearchBar = Input + Button)、表單欄位組 (FormGroup = Label + Input + ErrorMessage)。
  • Organisms (組織): 完整的介面區塊。例如:導覽列 (Navbar)、產品卡片 (ProductCard)、頁尾 (Footer)。
  • Templates (模板) / Layouts: 頁面的骨架。

實作範例:封裝一個通用的 Input 分子 (Molecules)

這個 Component 自動處理了 Label、Input 本體以及錯誤訊息顯示,大幅減少 View 裡面的重複代碼。

@props(['label', 'name', 'type' => 'text']) // 定義傳入屬性

<div class="mb-4">
    <label for="{{ $name }}" class="block text-sm font-medium text-gray-700">
        {{ $label }}
    </label>
    
    <div class="mt-1 relative rounded-md shadow-sm">
        <input 
            type="{{ $type }}" 
            name="{{ $name }}" 
            id="{{ $name }}"
            {{ $attributes->merge(['class' => 'focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md']) }}
            @error($name) aria-invalid="true" @enderror
        >
    </div>

    @error($name)
        <p class="mt-2 text-sm text-red-600" id="{{ $name }}-error">{{ $message }}</p>
    @enderror
</div>

3. 拒絕在 View 裡面寫邏輯:善用 View Model 與 DTO

這是 Eric 最常碎念的一點:View 應該只負責顯示,不應該負責計算。

如果你發現自己在 Blade 裡面寫了複雜的 @if ($user->orders->where('status', 'paid')->sum('total') > 1000),請立刻停下來。這種邏輯難以測試,且讓 View 變得極其脆弱。

解決方案:View Models 或 Presenters

在 2026 年,我們更傾向使用 View Models(視圖模型)將資料「準備好」再丟給 Blade。這可以是一個簡單的 PHP Class,負責將資料庫的原始資料轉換成人類可讀的格式。

// app/ViewModels/OrderSummaryViewModel.php
class OrderSummaryViewModel
{
    public function __construct(public User $user) {}

    public function isVip(): bool
    {
        return $this->user->orders->where('status', 'paid')->sum('total') > 1000;
    }

    public function formattedTotal(): string
    {
        return number_format($this->user->orders->sum('total'), 2);
    }
}

Blade 內的使用變得極其清爽:

@if($viewModel->isVip())
    <x-ui.badge variant="gold">VIP 會員</x-ui.badge>
@endif

<span>總消費:{{ $viewModel->formattedTotal() }}</span>

4. Blade 效能優化:別忘了 View Caching

雖然 Blade 編譯後是 PHP 檔案,速度很快,但在高流量網站下,如果每個 Request 都要重新渲染大量不變的 HTML 片段(例如複雜的選單、Footer),依然是效能殺手。

在 Laravel 13 中,我們可以更積極地結合 Redis 來快取 View 的片段。雖然 Laravel 內建沒有直接的 @cache 指令(需依賴第三方套件或自製 Directive),但我們可以透過 Component 的 shouldRender 方法來控制。

進階技巧:使用 Fragment Caching

如果你不想引入複雜的套件,可以簡單地利用 Cache Facade 包裹渲染邏輯,或者使用像 Redis 進行快取優化

5. Slot 的進階用法:具名插槽與作用域插槽

很多工程師只會用預設的 {{ $slot }}。但在製作複雜組件(如 Data Table 或 Modal)時,具名插槽(Named Slots)是保持程式碼整潔的關鍵。

<x-ui.modal>
    <x-slot:title>
        刪除確認
    </x-slot>

    <p>您確定要刪除這筆資料嗎?此動作無法復原。</p>

    <x-slot:footer>
        <x-ui.button variant="secondary" @click="open = false">取消</x-ui.button>
        <x-ui.button variant="danger" wire:click="delete">確認刪除</x-ui.button>
    </x-slot>
</x-ui.modal>

這種寫法讓 Component 內部的 HTML 結構(Header, Body, Footer)由 Component 自身控制,而內容由外部注入,實現了完美的「控制反轉」(IoC)。

結論:View 是產品的臉面,請善待它

在 2026 年,全端開發的界線越來越模糊。無論你是寫 Livewire 還是純 Blade,良好的 View 層架構都是專案長久維護的基石。把 Component 當作你的 DSL(領域特定語言)來設計,你會發現寫 HTML 不再是苦差事,而是一種組裝藝術。

如果你發現現有的專案已經無法負荷業務成長,或者 View 層邏輯已經失控,這時候除了重構,也許你需要更系統性的架構檢視。

延伸閱讀

🚀 您的 Laravel 專案需要技術救援嗎?

不管是程式碼重構、效能優化,還是企業級系統開發,浪花科技的資深團隊都能為您提供最強力的技術後盾。別讓技術債拖垮您的商業佈局。

👉 立即聯繫我們,預約技術諮詢

// FAQ

常見問題

Blade 為什麼建議改用 Component 而非 @include?
@include 無法強制規範傳入的數據型別,也難以封裝獨立邏輯。Blade Component 則提供更強的封裝能力:透過 Attribute Bag 自動處理 HTML 屬性合併、用 Slots 讓結構更靈活、並可在 Class-based Component 中利用 PHP 型別系統驗證傳入資料,因此在現代開發中更適合作為標準做法。
如何用原子設計(Atomic Design)組織 Blade 的元件目錄?
可在 resources/views/components 下依層級分類:Atoms 是不可再分割的最小單位如按鈕、輸入框、圖標;Molecules 是由原子組成的群組如搜尋列、表單欄位組;Organisms 是完整介面區塊如導覽列、產品卡片、頁尾;最上層是 Templates/Layouts 頁面骨架。這種分層能讓工程師快速找到對應檔案。
為什麼不應該在 Blade View 裡寫業務邏輯?
View 應該只負責顯示,不應負責計算。在 Blade 裡寫複雜判斷(例如直接計算使用者已付款訂單總額是否超過門檻)難以測試,且讓 View 變得脆弱。建議改用 View Model 或 Presenter,先把資料「準備好」並轉成人類可讀格式,再丟給 Blade,讓模板保持清爽。
Laravel Blade 在高流量網站下如何做效能優化?
雖然 Blade 編譯後是 PHP 檔速度很快,但每個 Request 都重新渲染大量不變的 HTML 片段(如複雜選單、Footer)仍是效能殺手。可結合 Redis 快取 View 片段(Fragment Caching),或透過 Component 的 shouldRender 方法控制是否渲染,減輕重複渲染負擔。
~/roamer-tech/newsletter // FREE
// newsletter

訂閱免費電子報

把 AI 自動化、企業系統設計與 WordPress / Laravel 開發的真實案例和可直接照做的技巧,整理成電子報寄給你。只寄精選內容、不灌垃圾信,一鍵就能退訂。

$
// final.exec()

準備好讓你的網站開始為你工作了嗎?