購物車頁的元件,就住在購物車頁的檔案裡。
前端專案的標準做法,是把元件收在一個資料夾:
resources/js/components/CartPage.jsx
resources/js/components/SearchModal.jsx
resources/js/components/MobileMenu.jsx
我沒有這個資料夾。我的元件寫在會用到它的那個 blade 檔案裡:
cart/index.blade.php 購物車頁 + 它的元件
partials/storefront/navbar.blade.php 導覽列 + 搜尋 + 手機選單 + 抽屜購物車
admin/products/_form.blade.php 商品表單 + 它的編輯器元件
因為改一個功能,只要開一個檔案。
要調整購物車頁,你打開 cart/index.blade.php,HTML 結構、Preact 元件、樣式、要打哪支 API,全部在眼前。不用在 blade 跟 jsx 之間跳來跳去,也不用猜「這個畫面到底是哪個元件渲染的」。
因為資料傳遞變成零成本。
元件需要初始資料、需要 API 網址、需要 CSRF token。在同一個 blade 檔裡,直接用 @json 印進去就好:
const initial = @json($cart);
const UPLOAD_URL = @json(route('admin.images.store'));
const CSRF = @json(csrf_token());
不需要 data-* 屬性、不需要在 window 上掛一坨設定、不需要為了讓前端拿到路由而做一支 config API。後端知道的東西,直接遞給前端。
反對的聲音通常是:關注點分離,結構、樣式、行為要分開。
但那是 2010 年的分法。現在大家都同意,真正的關注點是「功能」,不是「語言」。 購物車頁的 HTML、樣式、行為是同一個關注點,它們一起改、一起壞、一起被刪掉。把它們拆到三個資料夾,才是把一個關注點切成三份。
React 生態圈自己也走到這裡了:元件裡面同時有 JSX、有 CSS-in-JS、有事件處理。我只是把這個範圍再放大一格,讓它連伺服器渲染的部分也一起住進來。
有元件在第二個地方被用到的時候。
我的做法是先不抽,等到真的重複了再說。目前整個網站,需要共用的只有購物車的操作邏輯(它被導覽列的抽屜、購物車頁、商品頁三處用到),那份我就抽成一個共用的 partial。
其餘的,每個元件只有一個家。找它的時候,去它服務的那個畫面找就對了。