Nuxt3をはじめる②

ルーティング
Nuxtではファイルシステムルータという仕組みを採用しており、pages/
ディレクトリ内に格納されたファイルに応じて自動的にルーティング(URLとコンポーネントの対応付け)が生成される。
pages/
ディレクトリ内に*.vue
ファイルを追加すると、自動でそのファイル名やフォルダ階層がURLに対応する。ルートに該当するファイルはindex.vue
というファイル名にする決まりがある。
my-nuxt-app
├ pages/
│ ├ index.vue # GET /で表示
│ ├ about.vue # GET /aboutで表示
│ └ users/
│ ├ index.vue # GET /usersで表示
│ └ [id].vue # GET /users/123で表示
└ ...
NuxtPageタグの内容がpages/
ディレクトリ内のtemplateタグ内の内容に置き換わるイメージ。
<template>
<div>
<NuxtPage />
</div>
</template>
<template>
<h1>Index</h1>
</template>
ページ間の移動
Nuxtのルーティング機能を利用してページリンクを作成するにはNuxtLinkタグを利用する。
スクリプトブロック内で遷移させる際は、userRouter()
を利用する。
<template>
<NuxtLink to="/about">Aboutへ移動</NuxtLink>
</template>
<script setup lang="ts">
const router = useRouter()
function goAbount() {
router.push('/about')
}
</script>

レイアウト
Nuxtにおけるレイアウトとは、ページ全体に共通する見た目や構造をまとめるための仕組みのことを指す。例えばヘッダー・フッターといった部分を毎ページに配置したい際、1つのレイアウトファイルにまとめておき、それらを各ページが利用するようにすれば、ページコンポーネントは個別の中身だけを記述すればよい仕組みになっている。
レイアウト機能を使う際は、layout/
ディレクトリに*.vue
ファイルを配置することでレイアウトファイルとして認識される。
my-nuxt-app
├ layouts/
│ ├ default.vue # デフォルトのレイアウト
│ └ admin.vue # admin用のレイアウト
└ ...
default.vue
という名前で記述したレイアウトファイルは、特定のレイアウトが適用されていない全てのページに適用されるデフォルトレイアウトとして機能する。
<template>
<header>
<h1>共通ヘッダー</h1>
</header>
<!-- ページコンテンツはここに差し込まれる -->
<slot />
<footer>
<p>共通のフッター</p>
<footer/>
</template>
<slot />
タグには後述するNuxtLayout
コンポーネントの子要素が挿入される。
このレイアウトを呼び出して適応させるには、NuxtLayout
コンポーネントを利用する。
<template>
<div>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
ページごとに利用するカスタムレイアウト
カスタムレイアウトを定義して、そのレイアウトを各ページで利用したい場合はdefinePageMeta()
関数を利用する。
<template>
<div>
これはアドミンページ用のレイアウトです
<slot />
おわり
</div>
<template/>
<script setup lang="ts">
definePageMeta({
layout: "admin"
});
</script>
<template>
<div>ページコンテンツ</div>
</template>

HTTPリクエストによるデータの取得
$fetch()
$fetch
はNode.jsで標準的に利用でき、HTTPリクエストを送信することが可能。
<script setup lang="ts">
const data = ref()
const res = await $fetch('https://hogehoge.com/data')
data.value = await res.json()
</script>
useAsyncData()
useAsyncData
関数はサーバーサイド・クライアントサイドの両方でデータ取得を簡単に行うための仕組み(らしい。正直まだよくわかってない)。
第一引数にキーを指定でき、このキーが同じuseAsyncData()の実行結果はキャッシュされることで、APIの呼び出し回数の節約に貢献する。
useAsyncData(
キー文字列,
(): Promise<取得データの型> => {
// データ取得処理
return 取得データ;
),
オプションのオブジェクト
);
useFetch()
useFetch()
関数はNuxtで更にデータ取得を簡単に行うための仕組み。
取得したデータはdata
プロパティに格納され、リアクティブなデータとして保持される。
useFetch()の引数、オプション
引数名 | 内容 |
---|---|
query | URLに付与されるクエリパラメータ |
method | HTTPメソッド |
body | リクエストボディ |
pick | 戻り値から一部のフィールドデータだけを取り出したい場合に使う |
transform | レスポンスを任意の形に加工したい場合に使う |
lazy | データの取得を後回しにして画面を先に読み込ませる |
useFetch()の戻り値オブジェクト
プロパティ名 | 内容 | データ形式 |
---|---|---|
data | 取得したデータがリアクティブに格納される | 初期値はnull |
pending | データの取得が完了したかどうかを表す | ローディング中はtrue, 完了後false |
error | データ取得に失敗した際にエラーオブジェクトが格納される | |
refresh | データを再取得する関数 | 非同期関数 |
useFetch(
アクセス先のURL,
オプションオブジェクト
);

よく使う処理を再利用可能な状態にする
Nuxtではプロジェクト内にcomposables/
ディレクトリを作成し、その中にuse◯◯.ts
というファイルを用意すると、どのコンポーネントからもインポート無しで呼び出すことができる仕組みがある。
これはComposableという仕組みで、コンポーネントでよく使う状態管理や関数を別ファイルにまとめておくことで再利用可能とすることを目的としている。
例えば以下のようにコンポーザブルを定義すると、各コンポーネントはuseCounter()
を呼び出すだけで、この中のincrement()
やdecrement()
のロジックを使い回せるようになる。
// 関数名はファイル名と同じにする
export function useCounter() {
const count = ref(0)
function increment() {
count.value++
}
function decrement() {
count.value--
}
return {
count,
increment,
decrement
}
}