2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Nuxt 3】基本機能をなんとなく理解する

Last updated at Posted at 2024-07-24

download.gif

Nuxtとは

logo-green-black.png

Nuxtとは、一言で言うと「Vueを便利にしたヤツ」です。

コンポーネント内のルールは基本的にVue.jsと同様です。

なので、Nuxtの学習をする際は、「プレーンなVue.jsと比較して何が違うのか」という点を理解することが重要です。

新規アプリケーションの作成

以下コマンドを実行することで、Nuxt3の新規アプリケーションが作成されます。

npx nuxi@latest init アプリケーション名

作成されてディレクトリに移動し、「npm run dev」コマンドを実行することで、開発サーバーが起動します。

cd アプリケーション名
npm run dev -- -o

開発サーバーが起動されていると、以下のようなNuxt3のウェルカムページが表示されます。Nuxtアプリケーションの作成ができました👏

Screenshot 2024-07-17 at 23.50.02.png

ディレクトリ構成

./
├── .git
├── .gitignore
├── .nuxt
├── README.md
├── app.vue
├── node_modules
├── nuxt.config.ts
├── package-lock.json
├── package.json
├── public
├── server
└── tsconfig.json

新規でアプリケーションを作成すると、👆のようなファイル・フォルダが作成されます。その中でも重要なものについて以下で紹介します。

app.vue

Vueで言うところのApp.vueで、Nuxtアプリケーションのルートコンポーネントです。

このファイルは、アプリケーション全体のレイアウトを定義するために使用されます。すべてのページやコンポーネントはこのファイル内でレンダリングされます

nuxt.config.ts

Nuxtアプリケーションの設定ファイルで、アプリケーションの全体的な設定、プラグインの追加、モジュールの設定、環境変数の定義などを行うことができます。

このファイルを使用して、Nuxtアプリケーションの挙動をカスタマイズします。

ルーティング

Vue.jsを使用したアプリケーション開発を行う際には、別途VueRouterをインストールすることで、ルーティングを実装しますが、Nuxtでは追加でライブラリのインストールをせずにルーティングを実装することができます。

Nuxtでは、「ファイルシステムルーティング」と呼ばれるシステムにより、ディレクトリ構造を元に自動的にルーティングを設定することができます。この機能を使用すると、手動でルートを設定する必要がなくなり、プロジェクトの構造がより直感的になります

基本

ファイルシステムルーティングを使用するには、app.vueファイルに<NuxtePage />を追加してください。
<NuxtePage />とはVueRouterで言うところの<router-view />で、この<NuxtePage />の部分に、アクセスされたURLに該当するコンポーネントが表示されます。

app.vue
<template>
  <div>
    <NuxtPage />
  </div>
</template>

次に、プロジェクトルートにpagesディレクトリを作成してください。

ファイルシステムルーティングは、このpagesディレクトリ配下で定義されたコンポーネントを元にルーティングを行います。

例えば、pagesディレクトリ配下にabout.vueを追加します。

pages/about.vue
<template>
  <div>
    <h1>About page</h1>
  </div>
</template>

ブラウザで「/about」にアクセスすると、上記で定義したコンポーネントpages/about.vueが表示されます。

Screenshot 2024-07-18 at 18.16.25.png

このように、アクセスさえたURLに対し、pages/配下から該当するコンポーネントを表示します。

「/」のようにルートにアクセスがあった場合はpages/index.vueが表示されます。

「/about」の場合でも、上記で紹介したpages/about.vueでもいいですが、pages/about/index.vueでも定義することが可能です。ですが、pages/about.vuepages/about/index.vue両方が定義されている場合は、pages/about.vueが優先的に表示されます。

ダイナミックルーティング

「/users/1」のように、パスパラメーターを定義したい場合には、/pages/users/[id].vueのようにコンポーネントを定義します。

/pages/users/[id].vue
<template>
  <div>
    <h1>User: {{ $route.params.id }}</h1>
  </div>
</template>

Screenshot 2024-07-18 at 18.24.39.png

<template>内からパスパラメータにアクセスする際には、$route.paramsからアクセスすることができます。

<script>内で、パスパラメーターにアクセスする際には、useRouteメソッドを使用してルートの状態を取得し、paramsから該当するパラメータにアクセスします。

<script lang="ts" setup>
const route = useRoute();
console.log(route.params.id); // 1
</script>

パラメータ名は自由に指定することができます。例えば/pages/users/[user_id].vueのように指定した場合は、$route.params.user_idのようにアクセスする必要があります。

また、パラメータはディレクトリ名で表現することも可能です。「/users/1/likes」のようなパスに対するコンポーネントを作成する際には、/pages/users/[id]/likes.vueのように定義することができます。

アクセスされたURL 表示されるコンポーネント
/ pages/index.vue
/about pages/about.vue または pages/about/index.vue
/users pages/users.vue または pages/users/index.vue
/users/1 pages/users/[id].vue または pages/users/[id]/index.vue
/users/1/likes pages/users/[id]/likes.vue または pages/users/[id]/likes/index.vue

また、pagesディレクトリから該当するページが見つからない場合は、以下のようにNuxtで用意された404ページが表示されます。

Screenshot 2024-07-19 at 6.14.17.png

画面遷移

template内では、NuxtLinkを使用して画面遷移リンクを作成することができます。propsのtoには、遷移先のURLを指定します。

<NuxtLink to="/about">About</NuxtLink>
<NuxtLink to="/">Home</NuxtLink>

script内で画面遷移を実装する場合は、navigateToメソッドを使用します。

navigateTo("/about");

エラーページ

Nuxtでは、コンポーネントのレンダリング時に何かしらのエラーが発生した場合や、存在しないURLに対してユーザーがアクセスを行った場合に表示するカスタムエラーページを作成することができます。

アプリケーションルートにerror.vueという名前でコンポーネントを作成します。propsとしてエラーオブジェクトを受け取り、エラーの内容を画面に表示するようなものです。

error.vue
<template>
  <div>
    <h1>{{ error.statusCode }}</h1>
    <NuxtLink to="/">Go back home</NuxtLink>
  </div>
</template>

<script setup lang="ts">
import type { NuxtError } from "#app";

const props = defineProps({
  error: Object as () => NuxtError,
});
</script>

試しに、存在しないURLに対してアクセスを行ったり、コンポーネントのレンダリング時に何かエラーが発生すると、以下のようにerror.vueの内容が表示されます。

Screenshot 2024-07-19 at 8.41.44.png

middleware

Nuxtでは、特定のルートへアクセスする際に処理を挟み込むことができる機能を提供しています。

ユーザーの認証、リダイレクト、ログインチェックなど、ルートに関連するロジックを実行するために使用されることが多いです。

ミドルウェアはmiddlewareディレクトリで定義しましょう。defineNuxtRouteMiddlewareを使用することでミドルウェアを定義することができます。navigateToで、遷移先を指定できて、abortNavigationを使用することで遷移を中断できます。

middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const user = getUser();

  if (!user.isLoggedIn) {
    return navigateTo('/login'); // ログイン画面に遷移
  }

  if (!user.isValid) {
    return abortNavigation(); // 遷移を中断
  }
});

ミドルウェアの適用は、各ページコンポーネントで行います。definePageMetamiddlewareオプションを使用します。適用するミドルウェアは配列形式で渡します。その為、1つのページに対して複数のミドルウェアを適用することも可能です。

<template>
  <div>
    <h1>About page</h1>
  </div>
</template>

<script lang="ts" setup>
definePageMeta({
  middleware: ["auth"],
});
</script>

また、ミドルウェアを定義したファイル名に.globalを付与することで、全てのページに対して適用されるミドルウェアを設定することもできます。

例えば今回作成したmiddleware/auth.tsを、middleware/auth.global.tsにすることで、全てのコンポーネントに対してミドルウェアが適用されます。

layouts

Nuxtでは、Layoutという仕組みを提供しています。

レイアウトでは、アプリケーション全体また特定の画面グループで共通のテンプレートを定義するための仕組みです。
これにより、各ページで共通する部分(ヘッダー、フッター、ナビゲーションバーなど)を一箇所で管理できます。

アプリケーションルートに、layoutsという名前でディレクトリを作成してください。ルールとして、レイアウト定義ファイルはlayoutsディレクトリの配下に置く必要があります。

layoutsディレクトリ配下にdefault.vueという名前で以下のようなコンポーネントを作成してください。

<slot />の位置に、画面毎のコンポーネントが表示されます。

layouts/default.vue
<template>
  <div>
    <nav class="navigation_bar">
      My awesome app
    </nav>
    <slot />
  </div>
</template>

<script setup lang="ts">
</script>

<style scoped>
.navigation_bar {
  width: 100%;
  height: 50px;
  background-color: rgb(246, 150, 24);
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 20px;
  font-weight: bold;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
</style>

次に、app.vueの記述を以下のように変更してください。NuxtLayoutを追加することでLayoutsシステムを使用することができます。

app.vue
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

これでレイアウトの適用が完了しました。ブラウザで色々な画面に遷移しても、常にlayouts/default.vueで定義した内容が表示されるようになります。

Screenshot 2024-07-19 at 6.58.15.png

Screenshot 2024-07-19 at 6.58.43.png

また、definePageMetaというメソッドのlayoutオプションを各コンポーネントで指定することで、デフォルトのレイアウトを適用したくない。または他のレイアウトを使用することもできます。

layoutfalseを指定することで、レイアウトの適用を無効化することができます。

<template>
  <div>
    <h1>About page</h1>
  </div>
</template>

<script lang="ts" setup>
definePageMeta({
  layout: false,
});
</script>

Screenshot 2024-07-19 at 7.03.55.png

layoutで、名前を指定することで、layouts配下の同名のレイアウトが適用されます。

layouts/custom.vue
<template>
  <div>
    <nav class="custom_navigation_bar">
      costom
    </nav>
    <slot />
  </div>
</template>

<script setup lang="ts">
</script>

<style scoped>
.custom_navigation_bar {
  width: 100%;
  height: 50px;
  background-color: rgb(24, 183, 246);
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 20px;
  font-weight: bold;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
</style>
<template>
  <div>
    <h1>About page</h1>
  </div>
</template>

<script lang="ts" setup>
definePageMeta({
  layout: "custom",
});
</script>

Screenshot 2024-07-19 at 7.06.02.png

Auto Imports

Nuxt3では「Auto Imports」という機能があり、特定のディレクトリ配下のコンポーネントはimport文を記述せずにインポートすることができます。

<template>
  <div>
    <Card />
  </div>
</template>

<script lang="ts" setup>
</script>

デフォルトでAuto Importsが有効化されているのは、components/composables/utils/ です。

これらはnuxt.config.tsにて、無効化・カスタマイズが可能です。

nuxt.config.ts
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  compatibilityDate: '2024-04-03',
  devtools: { enabled: true },
  imports: {
    autoImport: false // 無効化
  }
})
nuxt.config.ts
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  compatibilityDate: '2024-04-03',
  devtools: { enabled: true },
  imports: {
    dirs: ["some_dir/**"], // some_dir配下をAuto importの対象に追加
  }
})

server

Nuxt3では、server/ディレクトリを利用して、サーバーサイドで実行される処理を定義することができます。
これを利用して、APIエンドポイントを実装することができます。

早速APIを作成してみましょう。以下のようにserver/api/hello.tsを定義してください。サーバー側の処理を定義する際には、defineEventHandlerというメソッドを使用します。

server/api/hello.ts
export default defineEventHandler((event) => {
  return {
    hello: "world",
  };
});

定義したAPIを、クライアントサイドから実行してみましょう。

Nuxtでは、データフェッチを行う際にはuseFetchというメソッドを使用します。今回はserver/api/hello.tsでAPIを作成したので、エンドポイントは/api/helloとなります。

<template>
  <div>
    <h1>About page</h1>
    <pre>{{ data }}</pre>
  </div>
</template>

<script lang="ts" setup>
const { data } = await useFetch("/api/hello");
</script>

以下のように、正常にデータフェッチができていることが確認できます。

Screenshot 2024-07-19 at 9.01.40.png

また、HTTPメソッド毎に処理を分けたい場合には、ファイル名を変えてあげるだけで可能です。.get.post.put.deleteを用いて定義したAPI Routeが対応するHTTPメソッドを指定することができます。

例えば以下のように、/api/helloというエンドポイントでGET、POSTを作成してみます。

server/api/hello.get.ts
export default defineEventHandler((event) => {
  return {
    message: "HTTP method is GET!",
  };
});
server/api/hello.post.ts
export default defineEventHandler((event) => {
  return {
    message: "HTTP method is POST!",
  };
});

GETでリクエストを送った際には、server/api/hello.get.tsで定義したサーバーアクションが実行されます。

<template>
  <div>
    <h1>About page</h1>
    <pre>{{ data }}</pre>
  </div>
</template>

<script lang="ts" setup>
const { data } = await useFetch("/api/hello");
</script>

Screenshot 2024-07-19 at 9.15.52.png

POSTでリクエストを送った際には、server/api/hello.post.tsで定義したサーバーアクションが実行されます。

<template>
  <div>
    <h1>About page</h1>
    <pre>{{ data }}</pre>
  </div>
</template>

<script lang="ts" setup>
const { data } = await useFetch("/api/hello", {
  method: "post",
});
</script>

Screenshot 2024-07-19 at 9.17.54.png

上記では単純に文字列を返却するAPI Routeを作成しましたが、Prisma等を使用してデータベースアクセスを行右ことも可能なので、本格的なAPIを実装することも可能です。

レンダリング手法の選択

Nuxtでは、ページのレンダリング方法を選択することができます。こちらは少し長くなるので、また別の記事でご紹介しようと思います。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?