Nuxt3のlayouts、pagesについて

# はじめに
この記事はlayouts、pagesの仕様や使い方について書いています。

大まかに以下の流れで説明していきます。
[1.app.vueについて](#1-appvueについて)
[2.layoutsについて](#2-layoutsについて)
[3.pagesについて](#3-pagesについて)

説明のために書くコードでは`<script setup>`構文を使用します。

https://v3.ja.vuejs.org/api/sfc-script-setup.html#%E5%9F%BA%E6%9C%AC%E3%81%AE%E6%A7%8B%E6%96%87


# 対象
Nuxt初心者の方、Nuxt2 → 3の変更点を知りたい方を対象にしています。
また、Nuxt3の環境構築は済んでいる前提で進めます。

# 環境
* Nuxt.js：3.0.0
* Vue.js：3.2.45

# 1. app.vueについて
まずは`app.vue`について説明しておきます。
Nuxt3ではプロジェクト立ち上げ時に`app.vue`ファイルが生成されるのですが、こちらを使用する場合は下記のようにコードを追加しないと`layouts/`と`pages/`のファイルが読み込まれません。
```vue
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>
```
`app.vue`に記述した内容は全てのコンポーネントに適用されますので全ての画面に反映させたい内容がある場合などに使用するといいみたいです。

https://nuxt.com/docs/guide/directory-structure/app

`app.vue`を削除すると今まで通りレイアウトファイル、ページファイルを自動的に読み込むようになります。

# 2. layoutsについて
以下について書きます。
1. レイアウトファイルでページファイルを読み込む方法
1. ページファイルでレイアウトを指定する方法

Nuxt3では`layouts`ディレクトリは自動で生成されなくなったのでまずはルートディレクトリに`layouts`ディレクトリを作成します。

## 2.1 レイアウトファイルでページファイルを読み込む方法
下記のように`<slot />`を使用して`ページファイルを読み込みます。
```vuejs
<template>
  <div>
    <slot /> // pages配下のファイルを表示する
  </div>
</template>
```
ちなみにnuxt2では`<nuxt />`で読み込んでいました。

## 2.2 ページファイルから指定する方法
レイアウトの設定方法ですが、`layouts/default.vue`であれば設定無しで自動的に読み込まれます。
それ以外のレイアウトを適用する場合はページファイルで下記のように指定します。
```vuejs
<script setup>
definePageMeta({ layout: 'foo' })
</script>
```
上記の例では`layouts/foo`を指定しています。
また、どのレイアウトも読み込みたくない場合は`definePageMeta({ layout: false })`のようにします。

# 3. pagesについて
以下について書いていきます。
1. NuxtPageで子ページを読み込む
1. metaタグの管理
1. 動的なルート

`layouts`と同じくNuxt3では`pages`ディレクトリが自動で生成されなくなりましたので、まずはルートディレクトリに`pages`を作成してください。

## 3.1 NuxtPageで子ページを読み込む
Nuxtでは下記のようなディレクトリ構成の場合、`parent.vue`に`<NuxtPage />`を記述すると`childe.vue`を読み込むことができます。
>┣ parent
 ┃    ┗ childe.vue
 ┗ parent.vue

```parent.vue
<template>
  <div>
    <NuxtPage />
  </div>
</template>

```
子ページ全てに反映させたい内容がある場合に使えるかと思います。
ちなみにNuxt2では`<Nuxt>`、もしくは`<NuxtChild>`で子ページを読み込んでいました。

## 3.2 metaタグの管理
metaタグの管理する方法は以下の3つがあります。
1. nuxt.config.tsで管理
1. Headタグを使用する
1. useHeadを使用する

ページファイルに関連する2、3のみ説明していきます。

### 3.2.1 Headタグを使用する
ページファイルの`template`内で`<Head>`を使用します。
```vuejs
<template>
  <div>
    <Head>
      <Title>タイトルです。</Title>
      <Meta name="description" content="説明です"/>
    </Head>
  </div>
</template>
```
`html`っぽく使えてわかりやすいですね。

### 3.2.2 useHeadを使用する
ページファイルの`script`内で下記のように記述する
```vuejs
<script setup>
useHead({
  title: 'タイトルです。',
  meta: [
    { name: 'description', description: '説明です' }
  ]
})
</script>
```
`nuxt2`では`head()`で指定していました。

補足になりますが、「**管理画面 - ログイン**」のようなタイトルの場合、「**管理画面**」の部分は固定にして「**ログイン**」の部分は画面によって動的に切り替わるようにしたいと思います。
そういった場合は下記のように記述します。
```pages/admin.vue
<script setup>
useHead({
  titleTemplate: (pageTitle) => {
    return pageTitle ? `管理画面 - ${pageTitle}` : '管理画面';
  }
})
</script>
```
`pageTitle`に各ページに設定したタイトルが入ります。

```pages/admin/login.vue
<script setup>
useHead({
  title: 'ログイン'
})
</script>
```
上記のように設定すると「**管理画面 - ログイン**」のように全体に適用する固定のタイトルと各ページごとに適用する動的なタイトルを設定する事ができます。

## 3.3 動的なルートについて
動的なルートにする場合、ファイル名のパラメータの部分を`[id].vue`のように角括弧で囲います。
```pages/[id].vue
<script setup>
const route = useRoute()
</script>

<template>
  <div style="margin: 50px">ID： {{ route.params.id }}</div>
</template>
```
`localhost:3333/1`のURLにアクセスできるか試してみてください。


# 最後に
ここまで見ていただきありがとうございました。
この記事では説明していない内容もありますのでもっと詳しく知りたい場合はドキュメントを確認してみてください。

https://nuxt.com/docs/migration/pages-and-layouts

# 参考
https://nuxt.com/docs/migration/pages-and-layouts/

https://nuxt.com/docs/guide/directory-structure/layouts

https://nuxtjs.org/docs/directory-structure/layouts/

https://nuxt.com/docs/getting-started/seo-meta#title-templates

https://kikuchance.com/2022/08/10/nuxt3-nuxtconfig-meta-bootstrap/