最終更新日: 2023年08月15日

ページ ディレクトリ

Nuxtは、Vue Routerを内部で使用してウェブアプリケーション内にルートを作成するためのファイルベースのルーティングを提供しています。

使用方法

ページはVueコンポーネントであり、Nuxtがデフォルトでサポートする有効な拡張子(.vue、.js、.jsx、.mjs、.ts、.tsxなど)を持つことができます。Nuxtは自動的に~/pages/ディレクトリ内の各ページに対してルートを作成します。

  • pages/index.vue
  • vue
<template>
  <h1>Index page</h1>
</template>
  • pages/index.ts
  • ts
// https://vuejs.org/guide/extras/render-function.html
export default defineComponent({
  render() {
    return h("h1", "Index page");
  },
});
  • pages/index.tsx
  • ts
// https://nuxt.com/docs/examples/advanced/jsx
// https://vuejs.org/guide/extras/render-function.html#jsx-tsx
export default defineComponent({
  render() {
    return <h1>Index page</h1>;
  },
});

pages/index.vue ファイルは、アプリケーションの/ルートにマッピングされます。

もし app.vue を使用している場合は、現在のページを表示するためにコンポーネントを使用してください。

  • app.vue
  • vue
<template>
  <div>
    <!-- 全てのページで共有されるマークアップ(例: ナビゲーションバー) -->
    <NuxtPage />
  </div>
</template>

ページは、ページ間のルートトランジションを可能にするために、単一のルートエレメントを持つ必要があります。(HTML コメントもエレメントとして考慮されます。)

これは、ルートがサーバーサイドでレンダリングされるか、静的に生成される場合は、そのコンテンツを正しく表示できるということを意味しますが、クライアントサイドのナビゲーション中にそのルートに向かうと、ルート間のトランジションが失敗し、ルートがレンダリングされないことがあります。

以下は、単一のルート要素を持つページの例です:

  • pages/working.vue
  • vue
// ○ 正しい記述方法 
// ※templeteタグの次はdivタグを必ず記述する
<template>
  <div>
    <!-- このページには1つの単一のルート要素のみなので、正常に動作します。 -->
    Page content
  </div>
</template>
  • pages/bad-1.vue
  • vue
// × 下記は悪い例です 
// ※templateタグの次に、不要なコメントが存在している
<template>
  <!-- このページは、クライアントサイドのナビゲーション中にルートが変更されると、このコメント文があるために、レンダリングされません。 -->
  <div>Page content</div>
</template>
  • pages/bad-2.vue
  • vue
// × 下記は悪い例です 
// ※templateタグの次にdivタグが複数存在している
<template>
  <div>このページは…</div>
  <div>複数のルート要素を持っています。</div>
  <div>クライアントサイドのナビゲーション中にルートが変更されるとレンダリングされなくなります。</div>
</template>

動的なルート

もし角括弧内に何かを配置すると、それは動的なルートパラメーターに変換されます。ファイル名やディレクトリ内に複数のパラメーターを組み合わせたり、動的でないテキストを含めることもできます。

もし、パラメータをオプションにしたい場合は、ダブルスクエアブラケットで囲む必要があります。例えば、~/pages/[[slug]]/index.vue や ~/pages/[[slug]].vue は、両方とも / や /test にマッチします。

  • ts
-| pages/
---| index.vue
---| users-[group]/
-----| [id].vue

上記の例では、コンポーネント内で$routeオブジェクトを介してgroupとidにアクセスできます。以下は具体的な例です:

  • vue
<template>
  <p>{{ $route.params.group }} - {{ $route.params.id }}</p>
</template>

/users-admins/123に移動すると、以下のようにレンダリングされます:

  • vue
<p>admins - 123</p>

もしComposition APIを使用してルートにアクセスしたい場合、グローバルなuseRoute関数が利用できます。これにより、Options APIのthis.$routeと同様にルートにアクセスできます。

  • vue
<script setup lang="ts">
  const route = useRoute()

  if (route.params.group === 'admins' && !route.params.id) {
    console.log('Warning! Make sure user is authenticated!')
  }
</script>

キャッチオール ルート

キャッチオールルートを必要とする場合は、[...slug].vue というようなファイルを作成します。これにより、そのパス以下のすべてのルートにマッチします。

  • pages/[...slug
  • vue
<template>
  <p>{{ $route.params.slug }}</p>
</template>

/hello/worldにアクセスすると、次のようにレンダリングされます:

  • vue
<p>["hello", "world"]</p>

ネステッドルート

<NuxtPage>を使用して、ネステッドルートを表示することが可能です。

Example:

  • ts
-| pages/
---| parent/
------| child.vue
---| parent.vue

以下のファイルツリーは、次のルートを生成します:

  • ts
[
  {
    path: '/parent',
    component: '~/pages/parent.vue',
    name: 'parent',
    children: [
      {
        path: 'child',
        component: '~/pages/parent/child.vue',
        name: 'parent-child'
      }
    ]
  }
]

child.vueコンポーネントを表示するには、pages/parent.vue内にコンポーネントを挿入する必要があります。

  • pages/parent.vue
  • vue
<template>
  <div>
    <h1>I am the parent view</h1>
    <NuxtPage :foobar="123" />
  </div>
</template>

チャイルドルートキー

<NuxtPage>コンポーネントが再レンダリングされるタイミングをより細かく制御したい場合(例:トランジション用)、pageKey プロップを介して文字列または関数を渡すか、definePageMeta を使用して key 値を定義することができます。

  • pages/parent.vue
  • vue
<template>
  <div>
    <h1>I am the parent view</h1>
    <NuxtPage :page-key="someKey" />
  </div>
</template>

または、次のようにすることもできます:

  • pages/child.vue
  • ts
<script setup lang="ts">
    definePageMeta({
        key: route => route.fullPath
    })
</script>

ページのメタデータ

アプリの各ルートにメタデータを定義したい場合があるかもしれません。definePageMeta マクロを使用することで、これを実現できます。このマクロは、<script> および<script setup>の両方で動作します。

  • ts
<script setup lang="ts">
    definePageMeta({
        title: 'My home page'
    })
</script>

このデータは、その後のアプリ全体でroute.metaオブジェクトからアクセスすることができます。

  • ts
<script setup lang="ts">
    const route = useRoute()
    console.log(route.meta.title) // My home page
</script>

もしネストされたルートを使用している場合、これらのルートからのページメタデータは1つのオブジェクトにマージされます。ルートのメタデータについては、vue-routerのドキュメントを参照してください。

definePageMetaは、defineEmitsやdefineProps(Vueのドキュメントを参照)と同様に、コンパイラのマクロです。コンポーネント内で参照することはできないため、コンポーネント内で参照することはできません。代わりに、それに渡されるメタデータはコンポーネントの外に持ち上げられます。したがって、ページのメタオブジェクトはコンポーネント(またはコンポーネントで定義された値)を参照することはできません。ただし、インポートされたバインディングは参照できます。

  • ts
<script setup lang="ts">
    import { someData } from '~/utils/example'

    const title = ref('')

    definePageMeta({
        title,  // This will create an error
        someData
    })
</script>

特別なメタデータ

もちろん、アプリ全体で独自の目的でメタデータを定義することはできますが、definePageMetaで定義された一部のメタデータには特定の目的があります:

  • エイリアス
    ページのエイリアスを定義することができます。これにより、異なるパスから同じページにアクセスできます。これは、vue-routerのドキュメントで定義されているように、文字列または文字列の配列であることができます。
  • KeepAlive

    definePageMeta で keepalive: true を設定すると、Nuxtは自動的にVueの<KeepAlive>コンポーネントでページをラップします。これは、例えば、動的な子ルートを持つ親ルートでページの状態をルートの変更を保持したい場合に便利です。

    親ルートの状態を保持することが目的の場合は、次の構文を使用します:<NuxtPage keepalive />。また、<KeepAlive>に渡すプロップスを設定することもできます(詳細なリストはこちらを参照してください)。

    このプロパティのデフォルト値をnuxt.configで設定することができます。

  • key
    上記を参照してください。
  • layout
    ルートのレンダリングに使用するレイアウトを定義することができます。これは、false(レイアウトを無効にするため)、文字列、またはref/computedのいずれかであり、リアクティブにする場合はref/computedを使用できます。レイアウトについての詳細はこちらを参照してください。
  • レイアウトトランジション と ページトランジション

    <transition>コンポーネントのトランジションプロパティを定義したり、特定のルートの<transition>ラッパーを無効にするために、nuxt.config.jsのpageTransitionとlayoutTransitionオプションを使用できます。これらのオプションを使用して、ページとレイアウトのトランジション効果をカスタマイズすることができます。

    プロパティのデフォルト値をnuxt.config.jsで設定することができます。

  • middleware
    ページを読み込む前に適用するミドルウェアを定義できます。このミドルウェアは、一致する親/子ルートのミドルウェアと結合されます。ミドルウェアは文字列、関数(グローバルなbeforeガードのパターンに従った無名/インラインのミドルウェア関数)、または文字列/関数の配列として定義することができます。詳細については、名前付きミドルウェアに関するドキュメントをご覧ください。
  • name
    ページのルートに名前を定義することができます。
  • path
    ファイル名で表現することができないより複雑なパターンがある場合、パスマッチャーを定義することができます。詳細はvue-routerのドキュメントを参照してください。

カスタムメタデータの型

ページにカスタムメタデータを追加する場合、型安全な方法で行いたい場合があります。definePageMetaで受け入れられるオブジェクトの型を拡張することができます。

  • index.d.ts
  • ts
declare module '#app' {
  interface PageMeta {
    pageType?: string
  }
}

// 型を拡張する際には、常に何かしらをインポート/エクスポートすることを確認することが重要です
export {}

ナビゲーション

アプリ内のページ間を移動するには、<NuxtLink>コンポーネントを使用する必要があります。

このコンポーネントはNuxtに含まれているため、他のコンポーネントと同様にインポートする必要はありません。

pagesフォルダー内のindex.vueページへの簡単なリンク:

  • vue
<template>
  <NuxtLink to="/">Home page</NuxtLink>
</template>

プログラムによるナビゲーション

Nuxt 3では、navigateTo() ユーティリティメソッドを介してプログラムによるナビゲーションが可能です。このユーティリティメソッドを使用することで、ユーザーをプログラムでナビゲートできます。これは、ユーザーからの入力を取得してアプリケーション内で動的にナビゲーションする場合に非常に便利です。以下の例では、シンプルな navigate() メソッドがあり、ユーザーが検索フォームを送信したときに呼び出されます。

注意: navigateTo メソッドを使用する際には、常に await するか、その結果を関数から返すようにチェーンしてください。

  • vue
<script setup lang="ts">
    const name = ref('');
    const type = ref(1);

    function navigate(){
        return navigateTo({
            path: '/search',
            query: {
            name: name.value,
            type: type.value
            }
        })
    }
</script>

カスタムルーティング

アプリが大きくなり、複雑になると、ルーティングがより柔軟性を必要とする場合があります。そのため、Nuxtは直接ルーター、ルート、およびルーターオプションをカスタマイズするためにさまざまな方法で公開しています。

複数のページディレクトリ

デフォルトでは、すべてのページはプロジェクトのルートにある1つのpagesディレクトリに配置されるべきです。しかし、Layersを使用してアプリのページをグループ化することができます。

  • ts
-| nuxt.config.ts
-| some-app/
---| nuxt.config.ts
---| pages
-----| app-page.vue
  • ts
// some-app/nuxt.config.ts
export default defineNuxtConfig({
})

// nuxt.config.ts
export default defineNuxtConfig({
  extends: ['./some-app'],
})