iT邦幫忙

2023 iThome 鐵人賽

DAY 8
0
Vue.js

Nuxt.js 3.x 筆記-打造 SSR 專案系列 第 8

D8:Nuxt 3.x Layouts 目錄-自訂模板

  • 分享至 

  • xImage
  •  

本篇文章同步更新於個人部落格,歡迎交流指教~謝謝您的閱讀

Layouts 資料夾協助我們定義共用模板,將重複使用的版面提取到模板內全域共用,看起來跟昨天介紹的 Components 有點像,那麼 Layouts 跟 Components 怎麼區分?可以將 Layouts 視為包覆在頁面外層的包裹元件,用來定義 Header、Sidebar、Footer 等共用版面或是元件

官方文件提到,如果整個專案只有一個模板,建議直接在 app.vue 定義即可

預設模板

預設模板名稱為 default,新增 layouts/default.vue,並透過 <slot /> 將元件的內容載入

// layouts/default.vue
<template>
  <div>
    <nav>Header</nav>
    <slot />
    <div>Footer</div>
  </div>
</template>

或是將 Header、Footer 等共用元件(Components)加入模板

// layouts/default.vue
<template>
  <div>
    <TheHeader />
    <slot />
    <TheFooter />
  </div>
</template>

接著在 app.vue 透過 <NuxtLayout> 元件使用模板,預設使用 layouts/default.vue 模板

// app.vue
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

新增首頁 pages/index.vue

// pages/index.vue
<template>
  <div>
    <h3>Home Page</h3>
  </div>
</template>

畫面呈現:


使用其他具名模板

layouts
|—— default.vue
|—— main.vue
// layouts/main.vue
<template>
  <div>
    <h2>Main Layout</h2>
    <slot />
  </div>
</template>

1. app.vue 指定全域模板,覆蓋預設模板

使用 name props 指定模板

名稱必須使用 kebab-case,例如 Layout 檔名為 customLayout,需使用 name='custom-layout'

// app.vue
<template>
  <NuxtLayout name="main">
    <NuxtPage />
  </NuxtLayout>
</template>

2. 在單一元件指定模板

使用 definePageMeta() 輔助函式指定模板名稱

// pages/index.vue
<template>
  <div>...</div>
</template>

<script setup>
definePageMeta({
  layout: 'main'
});
</script>

3. 在單一元件直接定義

先將預設模板設為 false,並透過 <NuxtLayout name="xxx"> 定義模板

// pages/index.vue
<template>
  <div>
    <NuxtLayout name="main">
      <h3>Home Page</h3>
    </NuxtLayout>
  </div>
</template>

<script setup>
definePageMeta({
  layout: false
});
</script>

在單一元件直接使用 <NuxtLayout>,要避免放在 根元素(root element),或是關閉 page 跟 layout 的 transitions 效果

畫面呈現:


動態切換模板

透過 setPageLayout() 輔助函式動態切換模板

// pages/index.vue
<template>
  <div>
    <h3>Home Page</h3>

    <button @click="setPageLayout('default')">default</button>
    <button @click="setPageLayout('main')">main</button>
  </div>
</template>


具名插槽

範例:

layouts/main.vue 搭配具名插槽

// layouts/main.vue
<template>
  <div>
    <nav>Header</nav>
    <slot name="content" />
    <div>Sidebar</div>
    <slot name="footer" />
  </div>
</template>

在頁面上使用,需將預設模板設為 false

// pages/index.vue
<template>
  <div>
    <NuxtLayout name="main">
      <template #content>
        <h3>Home Page</h3>
      </template>

      <template #footer>
        <h3>Footer</h3>
      </template>
    </NuxtLayout>
  </div>
</template>

<script setup>
definePageMeta({
  layout: false
});
</script>


參考資源:
https://nuxt.com/docs/guide/directory-structure/layouts
https://medium.com/codex/nuxt3-layouts-276ed64a4a1c
https://garywoodfine.com/how-to-use-layouts-in-nuxt-3/


上一篇
D7:Nuxt 3.x Components 目錄-建立共用元件
下一篇
D9:Nuxt 3.x Composables vs Utils 目錄-自訂共用方法
系列文
Nuxt.js 3.x 筆記-打造 SSR 專案30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言