【Nuxt 3】ページの構成について
基本構成
Nuxt 3では、基本的にレイアウト(Layout)、ページ(Page)、コンポーネント(Component)の3つで1つのページを構成します。 これはNuxt 2のときから変わりありません。
イメージは上図のような感じでしょうか。 レイアウトでヘッダーやサイドメニューのように各ページで共通の部分を作成します。 ページはコンポーネントとして分割した部品で構成し、ルーティングによって切り替わります。
Nuxt 3からはapp.vue
が使用できるようになっています。
ここでは<NuxtLayout>
や<NuxtPage>
を用いて上記の基本構成の定義します。
下記のような構成を使用する場合、app.vue
はプロジェクトから削除していても動作します。
<template>
<div>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
レイアウトやページが不要な場合は使用する必要はありません。
Nuxtの最小構成としてapp.vue
だけでアプリケーションを作成することもできますが、それはNuxtでなくても良いのでは?となりそうですね。
それでは以下よりそれぞれの機能や役割について深掘りしていきます。
ページ
まずはページから説明していきます。 レイアウトやコンポーネントは使用せずともアプリケーションの構築は可能ですが、ページはルーティングの役割を担うのでNuxtを使用する上では必須と言えます。
ルーティング
/pages
フォルダに作成したVueファイルがそのままページの役割を持ったファイルとなります。
ここで重要なのは、/pages
のフォルダ構成がそのままルーティングの設定となることです。
以下は簡単な例になります。
/pages
┝ /user
│ ┝ [id].vue → /user/{id}
│ ┝ edit.vue → /user/edit
│ └ index.vue → /user
┝ about.vue → /about
└ index.vue → /
見ての通りだとは思いますが、フォルダ階層やファイル名によってルーティングが設定されているのがわかるかと思います。
パスパラメータを使用する場合は、ファイル名またはフォルダ名を[]
で囲みます。
Nuxt 2では先頭にアンダーバーをつけていましたが、Nuxt 3から変更されていますので注意してください。
またパスの一部をパスパラメータとすることが可能になっています。
例えばuser-[group].vue
というファイルを作った場合、[group]
の部分がパスパラメータとして扱われます。
具体的に、/user-admin
というパスでは、group = 'admin'
となります。
パスパラメータの値を含め、ルーティングの情報はuseRoute()
で参照します。
<script setup>
const route = useRoute()
const id = route.params.id //パスパラメータ[id]の取得
</script>
fullPath
:クエリを含めた現在パスpath
: 現在のパスquery
:クエリパラメータparams
:パスパラメータname
:ルーティングに設定された名前(フォルダ名-ファイル名)
ページ遷移
ページを遷移するには<NuxtLink>
を使用します。
例えば/about
に遷移する場合は以下のように記述します。
<NuxtLink to="/about">about</NuxtLink>
パスが一致するリンクには、router-link-active
とrouter-link-exact-active
クラスが付与されます。
このクラスによってアクティブなリンクのスタイルを変更します。
Nuxt 2では active と exact active が明確に使い分けられていたのですが、Nuxt 3ではすべて exact active となっているようです。
Nuxt 2のexact
プロパティがデフォルトで設定されているような状態です。
しかし、Nuxt 3の<NuxtLink>
にはexact
プロパティがないのですよね。
スタイル設定をする場合は注意が必要です。
Script上でページ遷移を実行したい場合は、useRouter()
を使用します。
const router = useRouter()
router.back() //1つ戻る
router.forward() //1つ進む
router.go(1) //引数の数値分進む(戻る)
router.push('/about') //指定したパスに遷移
router.replace('/about') //指定したパスに置換
ただし、push()
とreplace()
については、代わりにnavigateTo()
を使用することが推奨されています。
navigateTo()
は自動インポートされるため、即座に使用することができます。
navigateTo('/about')
navigateTo({
path: '/about',
query: {
param1: 1,
param2: 'abc'
}
})
headの設定
<title>
や<meta>
をページごとに設定するには、useHead()
を使用します。
<script setup>
useHead({
title: 'About Page',
meta: [
{ name: 'description', content: 'Aboutのページです。'}
]
})
</script>
もう一つ、<Head>
を使用する方法があります。
Scriptではなく、Template部分に記述します。
<template>
<Head>
<Title>{{ title }}</Title>
<Meta name="description" :content="description" />
</Head>
<div class="contents">
</div>
</template>
<script setup>
const title = 'About Page'
const description = 'Aboutのページです。'
</script>
middleware
middlewareは、ページがレンダリングされる前に実行したい処理を定義します。
例えば、ページの認可処理などに使用します。
middlewareの処理はページに直接記述することもできますが、
多くは/middleware
フォルダに作成します。
export default defineNuxtRouteMiddleware((to, from) => {
const auth = useState('auth')
if (!auth.value.authenticated) {
return navigateTo('/login')
}
})
to
、from
はそれぞれ遷移後、遷移前のroute
の情報になります。
例えば遷移後のパスパラメータを参照したい場合は、to.params.id
とします。
また条件により遷移先を変更する場合は、navigateTo()
を使用します。
ページごとにmiddlewareを設定するには、以下のようにdefinePageMeta()
を使用します。
<script setup>
definePageMeta({ middleware: 'auth' })
</script>
すべてのページに適用する場合は、/middleware
フォルダにxxxx.global.js(ts)
のようにglobal
を含めた名前のファイルを作成します。
レイアウト
レイアウトのファイルは、/layouts
フォルダに作成します。
Nuxt 2と同様にデフォルトではdefault.vue
の内容が反映されます。
<template>
<header>Header</header>
<main>
<slot />
</main>
<footer>Footer</footer>
</template>
Nuxt 2では、ページの表示部分を<Nuxt />
としていましたが、Nuxt 3からは<slot />
を使用するようになります。
ページで使用するレイアウトを変更したい場合は、definePageMeta()
のlayout
に設定します。
<script setup>
definePageMeta({ layout: 'other' })
</script>
コンポーネント
最後にコンポーネントについて説明していきます。
コンポーネントは先述したように、ページを構成するための部品を作成するイメージです。
これらは/components
フォルダに作成していきます。
コンポーネントの読み込み
コンポーネントは自動インポートされるため、簡単に使用することができます。
基本的にコンポーネント名 = ファイル名となります。
例えば/components/MyComponent.vue
の場合は、<MyComponent />
または<my-component />
で使用します。
/components/hoge/MyComponent.vue
のようにフォルダ階層を用いる場合は、<HogeMyComponent />
とフォルダ名もコンポーネント名に含めます。
フォルダ名をコンポーネント名に含めたくない場合は、以下のようにnuxt.config.js
を設定します。
export default defineNuxtConfig({
components: [{
path: '~/components/',
pathPrefix: false,
}]
})
useAsyncData, useFetch
Nuxt 2ではasyncData
やfetch
を用いてレンダリング前に外部からデータを取得していました。
asyncDate
はページ専用で、fetch
はコンポーネントでも使用することができました。
Nuxt 3からは代わりにuseAsyncData
とuseFetch
を使用します。
どちらもページに限らずコンポーネントでも使用できます。
これらの詳細についてはまた別の記事で紹介できたらと思っています。
エラーページ
Nuxt 2ではエラーページは/layouts/error.vue
に作成していました。
Nuxt 3からはプロジェクトのルートにerror.vue
を作成します。
<template>
{{ error.message }}
<button @click="handleError">clear error</button>
</template>
<script setup>
const props = defineProps({ error: Object })
const handleError = () => clearError({ redirect: '/' })
</script>
エラーの情報はerror
プロパティとして受け取ります。
またエラーページから戻る場合は、clearError()
を用い、redirect
に戻り先のページのパスを指定します。
意図的にエラーページを表示したい場合は、以下のようにshowError()
を使用します。
showError('Error Message!!')