레이아웃
레이아웃 (Layouts)
여러 페이지에 걸쳐 반복되는 UI 패턴, 예를 들어 헤더·푸터·사이드바 같은 공통 뼈대가 있다면 매 페이지마다 붙여 넣기보다 한 곳에 모아 재사용하고 싶을 거예요. Nuxt는 이런 공통 UI 패턴을 재사용 가능한 레이아웃으로 뽑아내는 layouts 프레임워크를 제공해요.
출처: 공식문서
본문
app/layouts/ 디렉터리에 두는 컴포넌트는 성능을 위해 사용할 때 비동기 임포트로 자동 로드돼요.
레이아웃 켜기
레이아웃은 app.vue에 <NuxtLayout>을 추가하면 켜져요.
<!-- app/app.vue -->
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
레이아웃을 사용하는 방법은 여러 가지예요.
- 페이지에서
definePageMeta로layout속성 설정 <NuxtLayout>의nameprop 설정- 라우트 규칙(route rules)에서
appLayout속성 설정
레이아웃 이름은 kebab-case로 정규화되어 someLayout은 some-layout이 돼요. 레이아웃을 지정하지 않으면 app/layouts/default.vue가 사용돼요. 애플리케이션에 레이아웃이 하나뿐이라면 app.vue를 쓰는 걸 권장해요.
다른 컴포넌트와 달리 레이아웃은 레이아웃 전환 시 트랜지션을 적용할 수 있도록 단일 루트 엘리먼트를 가져야 하고, 그 루트 엘리먼트는 <slot />이면 안 돼요.
기본 레이아웃
~/layouts/default.vue를 추가해요.
<!-- app/layouts/default.vue -->
<template>
<div>
<p>Some default layout content shared across all pages</p>
<slot />
</div>
</template>
레이아웃 파일에서 페이지의 내용은 <slot /> 컴포넌트에 표시돼요.
이름 있는 레이아웃
-| layouts/
---| default.vue
---| custom.vue
그런 다음 페이지에서 custom 레이아웃을 이렇게 사용해요.
<!-- pages/about.vue -->
<script setup lang="ts">
declare module 'nuxt/app' {
interface NuxtLayouts {
'custom': unknown
}
}
// ---cut---
definePageMeta({
layout: 'custom',
})
</script>
<NuxtLayout>의 name 속성으로 모든 페이지의 기본 레이아웃을 직접 바꿀 수도 있어요.
<!-- app/app.vue -->
<script setup lang="ts">
// API 호출이나 로그인 상태에 따라 고를 수 있어요
const layout = 'custom'
</script>
<template>
<NuxtLayout :name="layout">
<NuxtPage />
</NuxtLayout>
</template>
중첩 디렉터리에 레이아웃이 있으면, 레이아웃 이름은 자신의 경로 디렉터리와 파일 이름을 기준으로 만들어지고 중복 세그먼트는 제거돼요. 헷갈림을 피하려면 레이아웃 파일 이름이 그 이름과 일치하도록 하는 걸 권장해요.
레이아웃 동적 변경
setPageLayout 헬퍼로 레이아웃을 동적으로 바꿀 수도 있어요.
<!-- app/pages/index.vue -->
<script setup lang="ts">
declare module 'nuxt/app' {
interface NuxtLayouts {
'custom': unknown
}
}
// ---cut---
function enableCustomLayout () {
setPageLayout('custom')
}
definePageMeta({
layout: false,
})
</script>
<template>
<div>
<button @click="enableCustomLayout">
Update layout
</button>
</div>
</template>
특정 경로에 대한 레이아웃은 라우트 규칙의 appLayout 속성으로도 지정할 수 있어요(v4.3+). 각 페이지 파일에서 관리하기보다 설정으로 중앙 관리하고 싶을 때, 또는 대응되는 페이지 컴포넌트가 없는 경로(여러 경로에 걸쳐 매칭될 수 있는 catchall 페이지 같은)에 적용하고 싶을 때 유용해요.
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
// 특정 경로에 레이아웃 지정
'/admin': { appLayout: 'admin' },
// 여러 경로에 레이아웃 지정
'/dashboard/**': { appLayout: 'dashboard' },
// 경로에 레이아웃 비활성화
'/landing': { appLayout: false },
},
})
레이아웃에 Props 넘기기 (+4.4)
레이아웃에 props를 넘기는 방법이 몇 가지 있어요. definePageMeta의 layout 속성을 객체 문법으로 쓰면 페이지에서 바로 props를 전달할 수 있는데, 레이아웃의 defineProps를 기준으로 완전히 타입이 잡혀 에디터에서 자동완성과 타입 검사를 받을 수 있어요.
<!-- app/pages/dashboard.vue -->
<script setup lang="ts">
definePageMeta({
layout: {
name: 'panel',
props: {
sidebar: true,
title: 'Dashboard',
},
},
})
</script>
setPageLayout으로 레이아웃을 동적으로 바꿀 때도 props를 넘길 수 있어요.
setPageLayout('panel', { sidebar: true, title: 'Dashboard' })
페이지 단위로 레이아웃 재정의
pages를 쓰고 있다면 layout: false로 두고 페이지 안에서 <NuxtLayout> 컴포넌트를 직접 쓰는 방식으로 완전히 제어할 수 있어요. 단, 페이지 안에서 <NuxtLayout>을 쓸 땐 그게 루트 엘리먼트가 되지 않게 해야 해요(그렇지 않으면 레이아웃/페이지 트랜지션을 꺼야 해요).
<!-- app/pages/index.vue -->
<script setup lang="ts">
definePageMeta({
layout: false,
})
</script>
<template>
<div>
<NuxtLayout name="custom">
<template #header>
Some header template content.
</template>
The rest of the page
</NuxtLayout>
</div>
</template>
더 알아보기
<NuxtLayout>,setPageLayout,definePageMeta세부 옵션은 API 문서를 참고하세요- 레이아웃 전환 트랜지션은 Views·Transitions 문서에서 다뤄요