本篇文章同步更新於個人部落格,歡迎交流指教~謝謝您的閱讀
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>
使用 name
props 指定模板
名稱必須使用 kebab-case,例如 Layout 檔名為 customLayout,需使用
name='custom-layout'
// app.vue
<template>
<NuxtLayout name="main">
<NuxtPage />
</NuxtLayout>
</template>
使用 definePageMeta()
輔助函式指定模板名稱
// pages/index.vue
<template>
<div>...</div>
</template>
<script setup>
definePageMeta({
layout: 'main'
});
</script>
先將預設模板設為 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/