iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0
Vue.js

Nuxt 3 初學者指南:30天從基礎到實踐系列 第 11

Day 11 – Nuxt 3 Layouts(佈局)

  • 分享至 

  • xImage
  •  

Layouts 在設計網頁時扮演重要的角色,提供共用的介面以保持多個頁面有一致的外觀與結構。
<NuxtLayout> 如果沒有指定 name,預設會使用 layouts/default.vue。使用方式為利用 <slot /> 來挖洞存放頁面的內容,當然也可以根據需求自定義多個不同的佈局。今天就來介紹如何有效的運用 Nuxt 3 的 Layouts。

單一佈局

Step 1

建立 layout

// layouts/default.vue
<template>
  <div>
    <h1>default layout</h1>
    <slot />
  </div>
</template>

Step 2

使用 <NuxtLayout> 元件

// app.vue
<template>
  <NuxtLayout> my contents </NuxtLayout>
</template>

https://ithelp.ithome.com.tw/upload/images/20230925/20162805J1VE7Fksuk.png

  • layouts/default.vue<slot /> 就是 app.vue<NuxtLayout> 內包裹元素的顯示位置,此處 "my contents" 可以換成 <NuxtPage />,將畫面設定為 /pages 對應的頁面。
  • 如果只有一個共用模板的話,官方文件建議可以直接在 app.vue 定義就好。
  • ⚠ 注意:layout 必須是單一的根元素且根元素不能是 <slot />,以確保在頁面切換、佈局更改時自動應用過渡效果(Transition)。

多個佈局

除了 layouts/default.vue 外,須使用其他佈局。
佈局名稱標準為 kebab-case,如果檔名為 creativePlanet.vue,則 layout 名稱會是 creative-planet

Step 1

建立 custom layout

// layouts/custom.vue
<template>
  <div>
    <h1>custom layout</h1>
    <slot />
  </div>
</template>

Step 2

需指定 <NuxtLayout>name,若無指定則會是 layouts/default.vue

  1. name 直接傳字串(name="要使用的佈局檔案名稱"

    // app.vue
    <template>
      <NuxtLayout name="custom"> my contents </NuxtLayout>
    </template>
    
  2. namev-bind 的方式綁定

    // app.vue
    <template>
      <NuxtLayout :name="layout"> my contents </NuxtLayout>
    </template>
    <script setup lang="ts">
    const layout = "custom";
    </script>
    
  3. 利用 definePageMeta() 覆蓋預設佈局

    // app.vue - 佈局為 layouts/default.vue 
    <template>
      <NuxtLayout> <NuxtPage/> </NuxtLayout>
    </template>
    
    // pages/index.vue - 佈局覆蓋為 layouts/custom.vue 
    <template>
      my contents
    </template>
    <script setup lang="ts">
    definePageMeta({
      layout: 'custom'
    })
    </script>
    

    nuxt devtools 查看 /layout 改為 custom ,其他頁面則會是(default)。

    https://ithelp.ithome.com.tw/upload/images/20230925/20162805FYYHgd6ejY.png

    ⚠ 注意:definePageMeta() 是用來設定頁面的 utils,因此只能在頁面元件(通常位於 pages/ 目錄下,也可以在 nuxt.config.ts 設定其他路徑)的 <script><script setup> 使用。如果嘗試在不符合上述條件的地方使用,將會失效並出現警告訊息:

    definePageMeta() is a compiler-hint helper that is only usable inside the script block of a single file component which is also a page. Its arguments should be compiled away and passing it at runtime has no effect.

    這意味著因為不符合上述條件,definePageMeta() 在執行時不會有任何效果。

以上三種方式的結果都會是:

https://ithelp.ithome.com.tw/upload/images/20230925/20162805yvmRfeJMw5.png

多個 slot 的佈局

Layouts 中可以插入自訂的具名 Slots,讓佈局有分區塊需求時,能更加靈活運用。

Step 1

建立具名的 slot 並設定預設內容。

// layouts/custom.vue
<template>
  <div>
    <h1>custom layout</h1>
    <h2><slot name="header"> default header content. </slot></h2>
    <main>
      <slot />
    </main>
  </div>
</template>

Step 2

使用時指定相對應的 slot 名稱,沒有指定的內容則會放在 <main> 區塊內。

// app.vue
<template>
  <NuxtLayout name="custom">
    <template #header> Some header template cotent. </template>
    The rest of the page.
  </NuxtLayout>
</template>

https://ithelp.ithome.com.tw/upload/images/20230925/20162805PxVrHhsu8y.png

結合 <NuxtLink> 應用

將多個頁面共用 Layout,並且可以在佈局內加上 <NuxtLink> 讓使用者能更輕鬆的切換頁面。

目前 layouts/pages/ 資料結構

nuxt-project  
 ┣ layouts              
 ┃  ┣ custom.vue
 ┃  ┗ default.vue
 ┣ pages          
 ┃  ┣ index.vue          
 ┃  ┣ about.vue
 ┃  ┗ service.vue

Step 1

增加 <NuxtLink>

// layouts/custom.vue
<template>
  <div>
    <div>
      <div>Welcome to CreativePlanet !</div>
      <NuxtLink to="/">Home</NuxtLink>
      <NuxtLink to="/about">Who we are</NuxtLink>
      <NuxtLink to="/service">What we do</NuxtLink>
    </div>
    <slot />
  </div>
</template>

Step 2

直接在 app.vue 使用,統一整個網站的佈局

// app.vue
<template>
  <NuxtLayout :name="layout">
    <NuxtPage />
  </NuxtLayout>
</template>
<script setup lang="ts">
const layout = "custom";
</script>

動態改變佈局

// pages/index.vue
<template>
  <div>
    <h1>Welcome to CreativePlanet !</h1>
    <button @click="EnableCustomLayout"> Update Layout </button>
  </div>
</template>
<script setup lang="ts">
const EnableCustomLayout = () => {
  setPageLayout('custom')
}
definePageMeta({
  layout: false
})
</script>

  • definePageMeta({ layout: false }) 表示該頁面預設不使用任何佈局,不可用於 app.vue
  • setPageLayout() 是 Nuxt 3 提供的 Utils,可用來動態變更頁面的佈局,可用於 app.vue

如果還沒建立專案的朋友,也可以先嘗試看看官方文件的線上 layouts 範例

🌞 Upcoming

這兩天介紹了 Pages 和 Layouts,明天會介紹 Middleware 的應用。


參考資料:

Layouts Directory


上一篇
Day 10 - Nuxt 3 Pages & Routing(頁面及路由)
下一篇
Day 12 – Nuxt 3 Middleware(中介層)
系列文
Nuxt 3 初學者指南:30天從基礎到實踐30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言