LoginSignup
5
1

Nuxt3 × Vuetify3 × TypeScript × SCSS × ESLintでプロジェクトをはじめるために

Last updated at Posted at 2023-12-20

はじめに

こんにちは、GxPの森下です!
この記事はグロースエクスパートナーズ Advent Calendar 2023の21日目の記事です。

案件でNuxt2を触ることになったので、勉強も兼ねて新しいNuxt3も触ってみたいと思い、進めていくうちに学んだことをまとめました。

※この記事では、Nuxt3の環境構築など基本的な内容が主であり、Vue3の構文についてはほとんど触れないため、ご了承ください。Vue3の詳細については、公式ドキュメントを参考にしてみてください。

環境

バージョン

  • OS : Windows11
  • Node.js : 20.10.0
  • npm : 10.2.3
  • npx : 10.2.3
  • Nuxt : 3.8.2

Nuxt3

NuxtはVueベースのフレームワークです。

プロジェクトの雛形の作成

bash
npx nuxi@latest init <project-name>
# または
npx nuxi init <project-name>

Nuxtのバージョンを指定したい場合は、nuxi@3.9.1のように書くことも出来ます。
※この時、プロジェクト名を記載しないと自動的にプロジェクト名はnuxt-appとなります。
上記コマンドを実行後、nodeを使用しているためnpmを選択。(依存関係のインストールに数分かかります。)

以下のコマンドでアプリを起動出来ます。

bash
# ディレクトリを移動
cd <project-name>

# 起動
npm run dev -- -o
# または
npm run dev

npm run devはアプリの起動のみで、新規タブは自動で開かれません。そのため、http://localhost:3000に自分でアクセスする必要があります。

Vue3には、Option APIとComposition APIの2つの選択肢がありますが、この記事ではComposition APIを使用して記載します。

Auto-imports

Nuxt3にはAuto-importsが備わっており、この機能によってVue.js APIsやプロジェクトのcomponents/composables/utils/ディレクトリ配下のものを明示的にimportせずに使用することが可能になっています。

拡張機能

Vue3では上記の拡張機能 (Volar) を入れることで、シンタックスハイライトなどを行ってくれるようになります。公式ドキュメントにも記載がありますが、Vue3のプロジェクトでは、Vue2用の拡張機能であるVeturは無効にするようにしてください。

Vuetify3

Vuetify3はVueのUIライブラリです。

Vuetify3の準備

インストール

bash
npm install -D @invictus.codes/nuxt-vuetify

プロジェクト直下に作成されたnuxt.config.tsに以下を追加

nuxt.config.ts
export default defineNuxtConfig({
    modules: [
      '@invictus.codes/nuxt-vuetify'
    ],
})

使用する際は、以下の<v-btn>のようにVuetify3のcomponentsv-appタグで囲む必要があります。

index.vue
<template>
  <v-app>
    <v-btn>Button</v-btn>
    <v-btn icon="mdi-account"></v-btn>
  </v-app>
</template>

v-btnでは上記のようにタグ内でiconを使用することが出来ます。その際は、mdi-に続くiconを使用することになり、以下のサイトのMDI - Icon searchから使用可能なiconを検索することが出来ます。

以上でVuetify3の準備は完了です。Vuetify3の以下の機能について紹介します。

  1. Theme
  2. Wireframes
  3. Styles and animations
  4. ComponentsとAPI

1. Theme

Vuetify3をのThemeを使用することで簡単にカラーテーマを設定・変更することができます。

Nuxt3でThemeを使用する際には、まずpluginを追加する必要があります。
プロジェクト直下にplugins/vuetify.tsというファイルを追加し、以下の内容を記載します。

plugins/vuetify.ts
import { createVuetify } from 'vuetify'

export default defineNuxtPlugin((nuxtApp) => {
  const vuetify = createVuetify({
    theme: {
      defaultTheme: 'light'
    }
  })

  nuxtApp.vueApp.use(vuetify)
})

デフォルトのテーマを設定するのに必要なのはこれだけです。デフォルトでは、lightdarkの2種類が用意されています。

テーマを切り替えるボタンを実装したい場合は、公式ドキュメントにもあるように以下のようなコードを記載します。

index.vue
<template>
  <v-app>
    <v-container>
      <v-btn @click="toggleTheme">Toggle Theme</v-btn>
    </v-container>
  </v-app>
</template>

<script setup lang="ts">
  import { useTheme } from 'vuetify'

  const theme = useTheme()

  function toggleTheme() {
    theme.global.name.value = theme.global.current.value.dark ? 'light' : 'dark'
  }
</script>

ここでは記載しませんが、カスタムテーマを作成し、そのテーマを適用することも可能です。
※上記を行う際、Nuxt3のデフォルトではpluginsの直下のファイルしかpluginとして追加されないため、更に下の階層のファイルを使用したい場合は別途nuxt.config.tsファイルに書き込む必要があります。以下に公式ドキュメントの例を示します。

nuxt.config.ts
export default defineNuxtConfig({
  plugins: [
    '~/plugins/bar/baz',
    '~/plugins/bar/foz'
  ]
})

2. Wireframes

Vuetify3では簡単にレイアウトを作成することができ、Wireframeとしてサンプルがいくつか用意されています。

例えば、Discordという名前で以下のようなWireframeが用意されており、右下にあるGitHubに飛ぶことで実際のコードを確認することが出来ます。

image.png

3. Styles and animations

Vuetify3にはスタイルの機能も備わっており、BootstrapやTailwind CSSのようにclassに指定することで簡単にスタイルを適用することが出来ます。大きく分けて以下の4つがあります。


CSS Reset

Vuetify3では、デフォルトでリセットCSSが適用されています。

ドキュメントにも記載がありますが、リセットCSSを無効化する場合、一部のスタイルには個別にリセットCSSを適用する必要があるようです。


Transitions

Vuetify3のTransitionsの機能を使用することで簡単に動きを付けることが出来ます。

Transitionsにはいくつか種類がありますが、その使用方法としては大きく分けて2つあります。
ここではv-fade-transitionを例に説明します。


まず、1つ目はv-menuのようにpropstransitionがある場合です。
v-menuの説明のページを見てみるとprops内にtransitionが存在することが分かります。

image.png

このようにtransitionがある場合は、以下の<v-menu transition="fade-transition">のようにtransitionを指定することが出来ます。

index.vue
<template>
  <div class="text-center">
    <v-menu transition="fade-transition">
      <template v-slot:activator="{ props }">
        <v-btn
          dark
          color="primary"
          v-bind="props"
        >
          Fade Transition
        </v-btn>
      </template>
      <v-list>
        <v-list-item
          v-for="n in 5"
          :key="n"
        >
          <v-list-item-title v-text="'Item ' + n"></v-list-item-title>
        </v-list-item>
      </v-list>
    </v-menu>
  </div>
</template>

2つ目は、v-cardのようにpropstransitionがない場合です。

transitionがない場合は、対象箇所を<v-fade-transition>タグで囲う必要があります。

index.vue
<template>
  <v-row justify="center" style="min-height: 160px">
    <v-col class="shrink">
      <v-btn class="ma-2" color="primary" @click="expand = !expand">
        Expand Transition
      </v-btn>

      <v-fade-transition>
        <v-card
          v-show="expand"
          height="100"
          width="100"
          class="mx-auto bg-secondary"
        ></v-card>
      </v-fade-transition>
    </v-col>
  </v-row>
</template>

<script>
  export default {
    data: () => ({
      expand: false,
      expand2: false,
    }),
  }
</script>

Material color pallette

Vuetify3には、Material colorsというものがあり、以下のようにclass名にbg-text-の後ろに続けて用意されている色の名前を加えることで簡単に色を設定することが出来ます。

index.vue
<template>
  <div class="bg-light-blue-darken-4 text-orange-darken-3 text-center">
    <span>sample text</span>
  </div>
</template>

上記のコードで、以下のようなスタイルが適用できます。
image.png


UTILITY CLASSES

Vuetify3では、基本的なスタイルが提供されており、class名にそれを追加することでスタイルを適用することが出来ます。
ここではFlexを例に説明していきます。

index.vue
<template>
  <div class="d-flex justify-center bg-surface-variant">
    <v-sheet
      v-for="n in 3"
      :key="n"
      class="ma-2 pa-2"
    >
      justify-center
    </v-sheet>
  </div>
</template>

上記のコードで、以下のようなスタイルが適用できます。
image.png


4. ComponentsとAPI

各ComponentにはAPIが用意されており、このAPIにはいくつか機能があるので、そのうち3つを紹介します。

ここでは、<v-data-table>を例にComponentsとそのAPIの使い方について説明します。


Props

Propsは、<v-data-table>に指定された形式でデータを渡すことで、そのデータを使用してComponentを作成してくれます。
以下は公式ドキュメントの例で、:items="items"<v-data-table>にデータを渡していることが分かると思います。

index.vue
<template>
  <v-data-table :items="items"></v-data-table>
  <v-data-table :items="items" /> <!-- Slotsを用いない場合などは、このように書くことも出来ます -->
</template>

<script setup>
  const items = [
    {
      name: 'African Elephant',
      species: 'Loxodonta africana',
      diet: 'Herbivore',
      habitat: 'Savanna, Forests',
    },
    // ... more items
  ]
</script>

:item<v-data-table>側で指定されているPropsの名前で、Propsには: (v-bind)をつける時とつけないときがあり、静的な値には:はつけませんが、上記のように動的な値には:をつけます。

Events

Eventsでは、ComponentのEventを受け取ることが出来ます。どんな時のEventをどのように受け取れるのかはAPIのページに記載されています。Eventは$eventで受け取ることが出来ます。言葉だけだと分かりづらいと思うので、以下に例を示します。

index.vue
<template>
    <v-data-table update:page="func($event)">
        <!-- 省略 -->
    </v-data-table>
</template>

上記のようにすることで、関数func()に受け取ったEventを引数として渡すことが出来ます。

Slots

Slotsでは、指定した箇所の値を書き換えたりすることが出来ます。Slotsは、v-slot:または#を使って指定することが出来ます。

以下の例では、書き換える場所としてheader.idを指定しており、後ろの="{ column }"で変数を与えています。この場合、指定しているものがheader.idのため、参照するものは公式ドキュメントのうち、header.${string} とさらにその中のcolumn: InternalDataTableHeaderになります。このInternalDataTableHeaderの中を見てみるとDataTableHeaderOmitしていることが分かると思います。
なので、InternalDataTableHeaderは、DataTableHeaderの一部を書き換えたものであり、以下のように{{ column.title.toUpperCase() }}とすることでidheadertitle (以下の場合、itemskeyがそのままheadertitleになるためidという文字) を大文字に変換することが出来るようなります。

index.vue
<template>
  <v-data-table :items="items">
    <template #header.id="{ column }">
      {{ column.title.toUpperCase() }}
    </template>
  </v-data-table>
</template>
<script setup>
  const items = [
      {
        id: 1,
        name: 'T-Shirt',
        size: 'M',
        color: 'Red',
        price: 19.99,
        quantity: 10
      },
      // ... more items
  ]
</script>

※ただし、上記のように#header.id="{ column }"と書いてしまうとESLintを設定した際に'v-slot' directive doesn't support any modifier.というエラーが出てしまうため、<template #[`header.id`]="{ column }">のように記載する必要があります。


公式ドキュメント以外に、GitHubも参考になると思いますので、余裕があれば覗いてみてください。

TypeSctipt

Nuxt3にTypeScriptを導入する方法についてです。

TypeSctiptの準備

インストール

bash
npm i -D typescript vue-tsc

nuxt.config.tsに以下を追加

nuxt.config.ts
export default defineNuxtConfig({
  typescript: {
    shim: false,       // Volar(拡張機能)を使用する場合はfalse
    strict: true,      // 厳密な型チェックを有効にする
    typeCheck: true    // 開発時の型チェックを有効にする(ビルドパフォーマンスを最適化するためデフォルトでは型チェックが行われない)
  }
})

設定の詳細については、以下を参照してください。

.vueファイルでTypeScriptを有効にする場合は、lang="ts"を記載する必要があります。

index.vue
<script setup lang="ts"></script>

基本的なTypeScriptの書き方についてはここでは割愛しますが、refRefについてのみ簡単に紹介しようと思います。
以下の内容は公式ドキュメントの内容を参考にしたものです。

index.vue
<script setup lang="ts">
  import { ref } from 'vue'
  import type { Ref } from 'vue'

  const year = ref<string | number>('2023')
  const month: Ref<string | number> = ref('12')

  year.value = 2023 // ok!
  month.value = 12  // ok!
</script>

上記のようにrefに直接、型を指定する事もできますが、Refを使用することで明示的に型を指定する事もできます。
refは初期値を設定し、型を記載しない場合は、型推論が行われます。

SCSS

Nuxt3にSCSSを導入する方法についてです。

SCSSの準備

インストール

bash
npm i -D sass

.vueファイルでSCSSを有効にする場合は、lang="scss"を記載する必要があります。

index.vue
<style lang="scss"></style>

ESLint

ESLintは、ECMAScriptのLintで、コーディング規約に準じているかの確認を行ってくれるものです。

プロジェクト直下に.eslintrcというファイルを作成し、各設定を記載していきます。


全体像をつかむために以下に概要を示します。

.eslintrc
{
  "root": true,       // プロジェクトの直下のeslintのファイルの場合に記載
  "env": {            // 環境変数の設定
    "browser": true,  // ブラウザ上で開発を行う場合に記載
    "node": true,    // nodeを使用する場合に記載
    "es2021": true,   // ここを記載する場合、以下の"ecmaVersion"は記載する必要はない
  },
  "parser": ,         // ESLintに構文を理解させるために記載
  "parserOptions": {
    "parser": ,              // parserが複数ある場合に記載
    "ecmaVersion": "latest", // ECMAScriptのバージョンを記載
    "sourceType": "module", // import/exportを使用する場合に記載(デフォルトではscript)
    "ecmaFeatures": {
      "jsx": true,          // jsx記法を使用する場合に記載
    },
  },
  "extends": [],  // 外部のルールセットを使用する場合に記載
  "plugins": [],  // pluginを使用する場合に記載
  "rules": {      // 個別にルールを定義する場合にこの中に記載
    "quotes": ["error", "single"]  // 「シングルクォートに統一する、違うものを使用したらエラーを出力する」という設定
  },
}

root

下の階層には別の設定を使用したい場合、その階層ごとにESLintのファイルを作成することが出来ます。

起動の際、ESLintは上の階層のESLintのファイルをマージしていき、"root": trueが記載されているファイルにたどり着くまで行われます。

内容が競合した場合は、下の階層のものが優先されます。


extends

ルールをrulesで1つずつ設定していくのは面倒なため、基本的には外部で用意されているものを使用し、個別で対応したいもののみをrulesに記載していくやり方が一般的だと思います。


※ESLintには上記で使用したファイル形式以外にも、JSJSON, YAML等、複数のファイル形式が用意されています。異なるファイル形式のESLintのファイルが同じ階層にあった場合は、ファイル形式によって優先度が異なるため注意が必要です。

Nuxt3でESLintを使うための設定

@nuxtjs/eslint-moduleの使用方法

インストール

bash
npm install -D eslint @nuxtjs/eslint-module

nuxt.config.tsに以下を追加

nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@nuxtjs/eslint-module'
  ]
})

オプションを設定することも出来ます。
オプションのデフォルト値は上記の公式ドキュメントを参照してください。


起動時に以下のようなlintOnStartfalseにするように促す警告が出ます。
実行が出来なくなるわけではないですが、falseにしないと起動時に時間がかかる場合があります。

Terminal
warning: LintOnStart is turned on, and it will check for all matching files.                    

lintOnStartfalseにするには以下のように記載します。

nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    ['@nuxtjs/eslint-module', {lintOnStart: false}]
  ]
})

ESLintのルールの適用

Nuxt ESLint packages (Nuxt2で使用)

このESLintのパッケージはNuxt2で使用されるものらしく、誤った内容を記載していました。こちらの記事を参考にされた方、申し訳ありません。この内容については、こちらのページを参考にしてみてください。Nuxt3で使用するパッケージについては、後述するnuxt/eslint-configで記載していますので、そちらをご覧ください。
(以下の内容はNuxt3で使用される@nuxt/eslint-configと比較できるように残しておきます。nuxtの後ろにjsがつかないものがNuxt3用なので、使用する際は注意してください。)

このルールは追加設定なしですぐに使え、ページやコンポーネントなどに対するNuxt固有のルールが含まれています。設定できるものとしては以下の2つがあります。

  • @nuxtjs/eslint-config
  • @nuxtjs/eslint-config-typescript

上記の2つには以下のものが含まれています。

  • vue-eslint-parser
    • Vueの構造を解析させるために必要なものです。
  • eslint-plugin-vue"plugin:vue/vue3-recommended"
    • "plugin:vue/vue3-recommended"はより多くのルール (PriorityA-C) を含んでおり、Vue3において推奨されるルールが適用されています。
  • typescript-eslint (@nuxtjs/eslint-config-typescriptのみ)
    • @typescript-eslint/eslint-pluginには100以上のルールが含まれており、TypeScriptのコードに特化したベストプラクティス違反やバグ、スタイル上の問題を検出してくれます。

@nuxtjs/eslint-config-typescript (@nuxtjs/eslint-config) の使用方法

インストール

bash
npm i -D @nuxtjs/eslint-config-typescript

.eslintrcに以下を追加

.eslintrc
{
    "extends": [
      "@nuxtjs/eslint-config-typescript"
    ]
}

TypeScriptを使用しない場合は、@nuxtjs/eslint-config-typescript@nuxtjs/eslint-configに置き換えてインストール・追加してください。

Nuxt ESLint packages (Nuxt3で使用)

こちらのパッケージにも@nuxtjs/eslint-config-typescriptと同様に以下のものが含まれています。

@nuxt/eslint-config の使用方法

インストール

bash
npm i -D @nuxt/eslint-config

.eslintrcに以下を追加

.eslintrc
{
    "extends": [
      "@nuxt/eslint-config"
    ]
}

最終的な.eslintrcファイル

各設定やルールの適応を行った.eslintrcファイルは以下のようになります。

.eslintrc (Nuxt2の場合)
{
  "root": true,
  "env": {
    "browser": true,
    "node": true,
    "es2021": true
  },
  "extends": [
    "@nuxtjs/eslint-config-typescript"
  ],
  "parserOptions": {
    "sourceType": "module"
  }
}

こちらもESLintのパッケージと同様にNuxt2のものを記載していたため、Nuxt3を使用する方は以下のものを使用してください。(上記の内容もNuxt3で使用される@nuxt/eslint-configと比較できるように残しておきます。)

.eslintrc (Nuxt3の場合)
{
  "root": true,
  "extends": [
    "@nuxt/eslint-config"
  ],
  "parserOptions": {
    "sourceType": "module"
  }
}

@nuxt/eslint-configには、Nuxt2用の.eslintrcで設定したenvの内容はすでに含まれているため、記載していません。(ECMAScriptのバージョンは、es6が設定されています。)

上記でESLintの準備が整ったので、ここからはESLintの内容を元にコードを整形する方法について説明します。以下では、基本的なコード整形はPrettierで行い、その後ESLintで整形するという流れを設定していきます。拡張機能をインストール後、settings.jsonで設定を行います。

拡張機能のインストール

Prettier

image.png

ESLint

image.png

VSCodeの設定

settings.jsonに以下を記載します。

settings.json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
}

settings.jsonCtrl + Shift + Pでコマンドパレットを開き、settings.jsonで検索することで以下のようにして開くことが出来ます。この際、既定の設定(JSON)ではなく、ユーザー設定を開く(JSON)ことに注意してください。

image.png

上記の設定で、保存時にコードを整形することが出来るようになります。
※上記の設定に加え、"editor.formatOnSave": trueを指定するとうまく整形されないことがあるため記載していません。

おまけ

ESLintについて調べている際に、よく見かけたものの自分は使用しなかったものについて参考程度に記載しておきます。

  1. eslint-plugin-nuxt
  2. eslint-plugin-prettier
  3. babel/eslint-parser

1. eslint-plugin-nuxt

"plugin:nuxt/recommended"には公式ドキュメントのルールがすべて含まれており、一貫性を確保するためのデフォルトを強制するルールが適用されます。

eslint-plugin-nuxtの使用方法

インストール

bash
npm i -D eslint-plugin-nuxt

.eslintrcに以下を追加

.eslintrc
{
  "extends": [
    "plugin:nuxt/recommended"
  ]
}

2. eslint-plugin-prettier

Prettierをあたかもリンターのルールのように動作させるプラグインらしいですが、現在は非推奨となっています。

eslint-plugin-prettierの使用方法

インストール

bash
npm i -D eslint-plugin-prettier
npm i -D -E prettier
npm i -D eslint-config-prettier

.eslintrcに以下を追加

.eslintrc
{
  "extends": ["plugin:prettier/recommended"]
}

以下に非推奨となっている旨が記載されていますので気になる方はご覧ください。

3. babel/eslint-parser

babelはES5以降のコードをそれ以前のものに変換できるツールで、babel/eslint-parserはBabelによって変換されたソースコード上で ESLint を実行できるようにするものです。

babel/eslint-parserの使用方法

インストール

bash
npm i -D @babel/core @babel/eslint-parser

.eslintrcに以下を追加

.eslintrc
{
  "parser": "@babel/eslint-parser",
}

実際に作ってみる

以下では、サンプルとしてHeader, Side Navigation, Footer, Mainの要素からなるプロジェクトを作ってみます。

app.vue

app.vueはNuxtにおけるメインのコンポーネントになります。
プロジェクト直下にあるapp.vueを以下のものに書き換えます。

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

<NuxtLayout> : layoutsディレクトリの内容を表示させるためのタグです。
<NuxtPage /> : pagesディレクトリの内容を表示させるためのタグです。

備考

  • Nuxtではディレクトリが重要な役割を果たしますが、以下の3つがあればとりあえずは問題ないかと思います。他のディレクトリについては興味があれば調べてみてください。

  • Nuxt3の雛形作成直後は、以下のディレクトリ (layouts, components, pages) は存在しないため、プロジェクト直下に作成する必要があります。

  • 以下の使用されていない、<script lang="ts" setup></script><style lang="scss"></style>は削除しても問題ありませんが、記載出来ることを明示するために残してあります。

layoutsディレクトリ

レイアウトを作成するためのディレクトリです。

layouts/default.vue
<template>
  <v-app>
    <DefaultHeader />
    <DefaultSideNav />
    <v-main class="d-flex align-center">
      <v-container>
        <slot />
      </v-container>
    </v-main>
    <DefaultFooter />
  </v-app>
</template>
<script setup lang="ts"></script>
<style lang="scss"></style>

v-appはVuetify3を使用するために必要なタグになり、v-からはじまるタグはVuetify3のタグになります。

componentsディレクトリ

コンポーネントを作成するためのディレクトリです。

Header

components/DefaultHeader.vue
<template>
  <v-app-bar color="primary" density="compact">
    <template #prepend>
      <v-app-bar-nav-icon />
    </template>

    <v-app-bar-title>Nuxt3 Tutorial</v-app-bar-title>

    <template #append>
      <v-btn icon="mdi-dots-vertical" />
    </template>
  </v-app-bar>
</template>
<script setup lang="ts"></script>
<style lang="scss"></style>

Side Navigation

components/DefaultSideNav.vue
<template>
  <v-card>
    <v-navigation-drawer
      v-model="drawer"
      :rail="rail"
      permanent
      @click="rail = false">
      <v-list-item
        prepend-avatar="https://randomuser.me/api/portraits/men/85.jpg"
        title="John Leider"
        nav>
        <template #append>
          <v-btn
            variant="text"
            icon="mdi-chevron-left"
            @click.stop="rail = !rail"></v-btn>
        </template>
      </v-list-item>

      <v-divider></v-divider>

      <v-list density="compact" nav>
        <v-list-item
          prepend-icon="mdi-home-city"
          title="Home"
          value="home"></v-list-item>
        <v-list-item
          prepend-icon="mdi-account"
          title="My Account"
          value="account"></v-list-item>
        <v-list-item
          prepend-icon="mdi-account-group-outline"
          title="Users"
          value="users"></v-list-item>
      </v-list>
    </v-navigation-drawer>
  </v-card>
</template>
<script setup lang="ts">
import { ref } from 'vue'

const drawer = ref<boolean>(true)
const rail = ref<boolean>(true)
</script>
<style lang="scss"></style>

v-layoutは固定の領域を作成するためのものです。主に配置される場所が固定されているものに対して使用します。

Footer

components/DefaultFooter.vue
<template>
  <v-footer class="d-flex flex-column justify-end pa-0" app>
    <div class="bg-teal d-flex w-100 align-center px-4">
      <strong>Get connected with us on social networks!</strong>

      <v-spacer />

      <v-btn
        v-for="icon in icons"
        :key="icon"
        class="mx-4"
        :icon="icon"
        variant="plain"
        size="small" />
    </div>

    <div class="px-4 py-2 bg-black text-center w-100">
      {{ new Date().getFullYear() }}<strong>Vuetify</strong>
    </div>
  </v-footer>
</template>
<script lang="ts" setup>
import { ref } from 'vue'

const icons = ref<string[]>([
  'mdi-facebook',
  'mdi-twitter',
  'mdi-linkedin',
  'mdi-instagram'
])
</script>
<style lang="scss"></style>

pagesディレクトリ

実際に画面に表示されるページを作成するためのディレクトリです。

pages/index.vue
<template>
  <v-sheet
    elevation="12"
    max-width="600"
    rounded="lg"
    width="100%"
    class="pa-4 text-center mx-auto">
    <v-icon class="mb-5" color="success" icon="mdi-check-circle" size="112" />

    <h2 class="text-h5 mb-6">You reconciled this account</h2>

    <p class="mb-4 text-medium-emphasis text-body-2">
      To see a report on this reconciliation, click
      <a href="#" class="text-decoration-none text-info"
      >View reconciliation report.</a
      >

      <br />

      Otherwise, you're done!
    </p>

    <v-divider class="mb-4" />

    <div class="text-end">
      <v-btn
        class="text-none"
        color="success"
        rounded
        variant="flat"
        width="90">
        Done
      </v-btn>
    </div>
  </v-sheet>
</template>
<script setup lang="ts"></script>
<style lang="scss"></style>

※ここで作成したファイル名がそのままパス名になります。index.vue/ (http://localhost:3000) になります。

以下を参照

完成画面

上記を組み合わせていくと以下のような画面になります。実際のコードはGitHubの方にもあげてあるので、気になる方は確認してみてください。

image.png

さいごに

最後までご覧いただきありがとうございました。
これからNuxt3を学び始める人や学び始めたばかりの人のお役に立てれば幸いです。

5
1
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
5
1