iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0
Modern Web

LV的全端開發體驗系列 第 10

Day10 拆分前端的組件及頁面流程

  • 分享至 

  • xImage
  •  

在前面的試作過程中,我們很陽春的刻了一個臨時的後台畫面來使用,然後每換一個頁面,我們就得複製一整個包含選單的組件檔案來修改,如果現在我改了後端的路由,那前端的路徑也肯定要改,但因為選單的部份是五六個後端頁面都有的,所以我們得改完全部的頁面才行,日後如果後台增加到二三十個頁面時,那這修改的量會讓你胃食道逆流到海角天邊去。

使用Vue做為前端框架,有一件很方便的事就是自訂組件,並把組件以標籤的方式來使用,這會大大的提高頁面程式碼的可讀性,也可降低程式碼的重覆,並讓後續的維護和擴充變得容易許多。

之前的管理後台左側選單有點老套,現在我們已經確認了後端的資料溝通方式了,所以也不用擔心資料傳不出來的問題,在設計上可以大膽一點,我們讓選單是貼在左側的滿版長條,右側全部空間都拿來顯示內容,

resources\js\Layouts\AuthenticatedLayout.vue

....略
<!-- Primary Navigation Menu -->
<!-- 把區塊寬度改為全寬滿版 -->
<div class="w-full mx-auto px-4 sm:px-6 lg:px-8">
....略

<!-- Page Heading -->
<!--調整header的z-index 要顯示出header的底部陰影線-->
<header class="bg-white shadow relative z-20" v-if="$slots.header">
  <!-- 把區塊寬度改為全寬滿版 -->
<div class="w-full mx-auto py-6 px-4 sm:px-6 lg:px-8">
  <slot name="header" />
</div>
</header>
            
....略

<!-- Page Content -->
<!--調整main的z-index 讓main在header之下-->
<main class="relative z-10">
<slot />
</main>    

resources\js\Pages\Backstage\Backstage.vue

<AuthenticatedLayout>
<template #header>
  <h2 class="font-semibold text-xl text-gray-800 leading-tight">管理中心</h2>
</template>

<!--後台主內容區-->
<div class="w-full bg-white flex">
  <!--左側選單-->
  <div class="w-48 max-w-96 bg-black text-white py-8 px-2 shadow-lg h-[calc(100vh_-_138px)]">
    <Link :href="route('backstage.banks')"
          class="block my-2 py-2 hover:bg-slate-50 hover:text-slate-900 text-center text-xl">
            管理題庫
    </Link>
    <Link :href="route('backstage.quizzes')"
          class="block my-2 py-2 hover:bg-slate-50 hover:text-slate-900 text-center text-xl">
            管理試卷
    </Link>
    <Link :href="route('backstage.tests')"
          class="block my-2 py-2 hover:bg-slate-50 hover:text-slate-900 text-center text-xl">
            管理測驗
    </Link>
    <Link :href="route('backstage.groups')"
          class="block my-2 py-2 hover:bg-slate-50 hover:text-slate-900 text-center text-xl">
            管理群組
    </Link>
  </div>

  <!--右側內容區-->
  <div class="w-5/6 p-4 flex flex-wrap">
    <div class="w-1/2 border rounded-xl flex p-4 h-48 bg-green-400">
        題庫:
    </div>
    <div class="w-1/2 border rounded-xl flex p-4 h-48 bg-sky-400">
        試卷:
    </div>
    <div class="w-1/2 border rounded-xl flex p-4 h-48 bg-yellow-400">
        測驗:
    </div>
    <div class="w-1/2 border rounded-xl flex p-4 h-48 bg-orange-400">
        群組:
    </div>
  </div>
</div>
</AuthenticatedLayout>

這個後台頁面是基於 BreezeAuthenticatedLayout 組件,我們可以在這個基礎上加入我們自己的組件,一個是左側選單,一個是右側的內容區,我們打算先把左側選單獨立出來成為一個組件。

resources\js\Layouts 目錄下建立一個 BackstageLeftMenu.vue,並將選單的程式碼搬過去

resources\js\Layouts\BackstageLeftMenu.vue
記得要引入 inertia 的 Link 組件

<script setup>
import { Link } from "@inertiajs/inertia-vue3";
</script>
<template>
  <!--左側選單-->
  <div class="w-48 max-w-96 bg-black text-white py-8 px-2 shadow-lg h-[calc(100vh_-_138px)]">
    <Link :href="route('backstage.banks')"
          class="block my-2 py-2 hover:bg-slate-50 hover:text-slate-900 text-center text-xl">
          管理題庫
    </Link>
    <Link :href="route('backstage.quizzes')"
          class="block my-2 py-2 hover:bg-slate-50 hover:text-slate-900 text-center text-xl">
          管理試卷
    </Link>
    <Link :href="route('backstage.tests')"
          class="block my-2 py-2 hover:bg-slate-50 hover:text-slate-900 text-center text-xl">
          管理測驗
    </Link>
    <Link :href="route('backstage.groups')"
          class="block my-2 py-2 hover:bg-slate-50 hover:text-slate-900 text-center text-xl">
          管理群組
    </Link>
  </div>
</template>

我們可以在原本的檔案位置使用 <BackstageLeftMenu /> 來引入這個組件,但這又回到老問題,每一個後台頁面都要再放一次這個組件,而且還要考慮每個頁面的選單項目是那個;

換個方向想,既然這個選單是後台所有頁面都必然存在的,那它當然可以視為是整體 layout 的一部份,這也是為什麼我要把它放在 layout 目錄下的原因;

那就把選單放在 AuthenticatedLayout 中吧:

<!-- Page Content -->
<main class="relative z-10">
    
<!--後台主內容區-->
<div class="w-full bg-white flex">
  <!--左側選單組件放在這-->
  <BackstageLeftMenu />

  <!--右側的內容會由slot來引入-->
  <slot />
</div>
</main>

resources\js\Pages\Backstage\Backstage.vue 內容少很多,可以專注在右側內容區上

<AuthenticatedLayout>
    <template #header>
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">管理中心</h2>
    </template>

    <!--右側內容區-->
    <div class="w-5/6 p-4 flex flex-wrap">
        <div class="w-1/2 border rounded-xl flex p-4 h-48 bg-green-400">
            題庫:
        </div>
        <div class="w-1/2 border rounded-xl flex p-4 h-48 bg-sky-400">
            試卷:
        </div>
        <div class="w-1/2 border rounded-xl flex p-4 h-48 bg-yellow-400">
            測驗:
        </div>
        <div class="w-1/2 border rounded-xl flex p-4 h-48 bg-orange-400">
            群組:
        </div>
    </div>
</AuthenticatedLayout>

除了這種選單類的可以拆之外,像是一些 css 比較複雜或是有可能多次重覆使用的標籤元件,也都可以拆,比如選單中的每個項目都有比較複雜的 css,之後要增加項目時又要再複製一堆一樣的 class,這時也可以把這個項目拆成組件,然後可以由組件來傳入相關的參數;

由於自建組件的狀況會很多,為了方便管理,我們建立一個 QuizComponents 資料夾來管理我們自己建立的這些組件,當然,多到一個程度,可以再開子資料夾來做分類:

resources\js\QuizComponents\MenuItem.vue

<script setup>
import { Link } from "@inertiajs/inertia-vue3";

//定義可以傳入的參數
defineProps({
  route: String,
});
</script>
<template>
  <Link :href="route"
        class="block my-2 py-2 hover:bg-slate-50 hover:text-slate-900 text-center text-xl">
    <!--提供插槽供外部使用-->
    <slot />
  </Link>
</template>

然後把選單項目組件引入到 resources\js\Layouts\BackstageLeftMenu.vue

<script setup>
import MenuItem from "@/QuizComponents/MenuItem.vue";
</script>
<template>
  <!--左側選單-->
  <div class="w-48 max-w-96 bg-black text-white py-8 px-2 shadow-lg h-[calc(100vh_-_138px)]">
    <MenuItem :route="route('backstage.banks')">管理題庫</MenuItem>
    <MenuItem :route="route('backstage.quizzes')">管理試卷</MenuItem>
    <MenuItem :route="route('backstage.tests')">管理測驗</MenuItem>
    <MenuItem :route="route('backstage.groups')">管理群組</MenuItem>
  </div>
</template>

現在的選單看起來是不是好讀多了?

以此類推,可以先把其他的後端頁面原本的選單html碼整理一下,你會得到一組清爽的前端頁面檔案。

今天先這樣,前端頁面的拆解並不是這麼單純的,除了版型的調整,我們還得重新定義前端的邏輯,這部份會使用上狀態管理,我們明天再來說明。


上一篇
Day09 拆分後端的邏輯-Service And Repository
下一篇
Day11 前端頁面狀態管理 - Pinia
系列文
LV的全端開發體驗30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言