Nuxt.js+Vuetify.jsを使ってブログを作っていこう

2021-08-23

はじめに

前回記事で、Nuxt.jsでブログを作ってみる。で素のnuxt.jsを触り始めました。 今回はGUIをよりリッチに整えて作っていきたいので、Vuetify.jsを入れて再度作り込んで行きます。 Material Design系のUIが手軽に作れるという触れ込みです。

Vuetify | Material Design Framework

前回記事と同じところまでをまずは作っていくということでさっそく始めましょう。

Nuxt.jsプロジェクトの新規作成(Vuetify.js)

基本的には選択肢を増やすだけです。 UI frameworkに今回は、Vuetify.jsを選択肢、 moduleには、Axiosと、Contentを追加しています。 それ以外は特に特筆する点はないかと思います。

Nuxtはデフォルトで選択できるUI Frrameworkが多くていいですよね。

PS C:\src\Nuxt> npx create-nuxt-app KokoDevVuetyfi

ひとまず設定としてこのようにしました。

create-nuxt-app v3.7.1
✨  Generating Nuxt.js project in KokoDevVuetyfi
? Project name: KokoDevVuetyfi
? Programming language: JavaScript
? Package manager: Yarn
? UI framework: Vuetify.js
? Nuxt.js modules: Axios - Promise based HTTP client, Content - Git-based headless CMS
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Static (Static/Jamstack hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using typescript)
? What is your GitHub username? kenpos    
? Version control system: Git

既存プロジェクトに追加する場合

今回のブログでは新規インストールでやり直しますが、自前のプロジェクトにVuetify.jsを追加する方法も取れます。

yarn add @nuxtjs/vuetify

nuxt.config.js

上記ファイルをこのように書き換えると良いって公式サイトにも書いてます。


{
  buildModules: [
    // Simple usage
    '@nuxtjs/vuetify',

    // With options
    ['@nuxtjs/vuetify', { /* module options */ }]
  ]
}

プロジェクトの実行

とりあえずコンソールの指示に従って打ち込みます。

cd .\KokoDevVuetyfi\ | yarn dev

http://localhost:3000/で立ち上げ確認します。

Continue ボタンを押すとこうなります。

プロジェクトフォルダをVisual Studio Codeで開く

code .

とりあえず、Visual Studio Codeで立ち上げて編集していきましょう。

不要なファイルを削除

componentsの中身は一通り削除します。(後で必要なものを自分で作っていきます。)

rm .\components\*
rm .\static\*
rm .\store\*
rm .\assets\*

タイトルとコンテンツが書かれたヘッダコンポーネントを作成

componentsフォルダにHeader.vueを作成します。

Bottom navigation を参考にアイコンボタン付きのHeaderを作ってみましょう。

Header.vue全体コード

Headerというているが、v-cardタグに記載していきます。 v-cardsコンポーネントの説明はこちらに記載があります。

Cards

一部引用します。

パネルから静的画像まであらゆるものに使用できる汎用性の高いコンポーネントです

こんな感じに書きました。

<template>
  <header>
    <v-card color="basil">
      <v-card-title class="text-center justify-center py-6">
        <h1 class="font-weight-bold text-h2 basil--text">
          心のデブを信じろ
        </h1>
      </v-card-title>
      <v-bottom-navigation v-model="value">
        <v-btn value="home" to="/">
          <span>Home</span>
          <v-icon>mdi-home</v-icon>
        </v-btn>

        <v-btn value="profile" to="/profile">
          <span>Profile</span>
          <v-icon>mdi-account</v-icon>
        </v-btn>
      </v-bottom-navigation>

    </v-card>
  </header>
</template>

v-button-navigationの中に、v-btnを並べていきます。 v-btnが押されたときには、pagesの中にある*.vueファイルからできるリンクに飛ぶようにしてあります。 例えば、profile.vueがあれば、to=/profileと書くことでリンクに飛ばすことが可能です。

今回は、基から入っていたinspier.vueをprofile.vueにファイル名を変更して作成しています。

v-iconではMaterial icon標準で使える用になっています。 使用できるIconはこちらを参考ください。

Material Design Icons

index.vue

トップページを作っていきます。 書いてあった内容には参考になる情報が沢山含まれていますが、煩雑なので全部削除します。

<template>
  <v-row justify="center" align="center">
    <v-col cols="12" sm="8" md="4">
      <v-card>
        <h2>Title1</h2>
      </v-card>
      <v-card>
        <h2>Title2</h2>
      </v-card>
    </v-col>
  </v-row>
</template>

代わりにこれを書いておきました。

inspier.vue -> profile.vue への書き換え

inspier.vueの名前をprifile.vueに変更します。

中身も、staticフォルダの中身を消したので画像周りは削除しておきましょう。

<template>
  <v-row>
    <v-col class="text-center">
      <blockquote class="blockquote">
        &#8220;First, solve the problem. Then, write the code.&#8221;
        <footer>
          <small>
            <em>—John Johnson</em>
          </small>
        </footer>
      </blockquote>
    </v-col>
  </v-row>
</template>

全ページを縦断する画面表示を作成

layout/default.vueの編集します。

nuxtのUIを使わないサンプルであれば、.nuxtフォルダ以下に居たファイルと同じ役目をします。 先程作成した、Headerをv-containerに追加しましょう。

<template>
  <v-app>
    <v-main>
      <v-container>
        <Header />
        <Nuxt />
      </v-container>
    </v-main>

    <v-footer
      :absolute="!fixed"
      app
    >
      <span>© {{ new Date().getFullYear() }}</span>
    </v-footer>
  </v-app>
</template>

実行結果

随分デフォルトファイルから変更しました。

./

./profile

Themeの変更

暗いブログってのはあまり好みではないのでDarkモードから色を変更します。 nuxt.config.jsを編集すうと叶います。

一部抜粋。

// Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
vuetify: {
  customVariables: ['~/assets/variables.scss'],
  theme: {
- dark: true,
+    dark: false,
    themes: {
      dark: {
        primary: colors.blue.darken2,
        accent: colors.grey.darken3,
        secondary: colors.amber.darken3,
        info: colors.teal.lighten1,
        warning: colors.amber.base,
        error: colors.deepOrange.accent4,
        success: colors.green.accent3
      }
    }
  }
},

themeの中にあるdarkをfalseにした際には色使いがこのようになります。

小学生のブリーフみたいな真っ白になりましたね。

記事の一覧を作成する

articlesフォルダを作る

pagesとcontentフォルダarticlesというフォルダを作成します。

記事情報の出力準備

_slug.vueを作成します。 nuxt-contentを使って、articlesのフォルダ内の.mdの冒頭タグから情報を引っ張ってきます。

<template>
 <article>
   <h1>{{articles.title}}</h1>
   <p>{{articles.date}}</p>
   <p>{{articles.datetimes}}</p>
   <nuxt-content :document="articles" />
 </article>
</template>

<script>
export default {
 async asyncData ({ $content, params }) {
   const articles = await $content('articles', params.slug || 'index').fetch()
   return { articles }
 }
}
</script>

トップページに表示する

index.vueを編集して行きます。

v-cardを使って各記事のタグ情報を書き出して並べていきます v-forでarticlesの中に含まれる要素を取り出していきます。 cols=autoとすることで、ブラウザのサイズに合わせて横に並べる個数を変えてくれるようになります。

各記事のリンクは:to="’/articles/’+b.slug"で指定します。 v-imgタグにはひとまずオンライン上の画像をリンクにしていますが、markdonwのタグから引っ張るようにすれば記事毎に画像を表示するようなこともできます。

<template>
 <v-container mt-50 pt-50>
    <v-row class="white" style="height: auto;">
    <v-col v-for="b in articles" :key="b.slug" cols=auto>
      <v-card
      max-height="400"
      max-width="400"
      min-height="400"
      min-width="400"
      elevation="3"
      class="mx-auto"
      outlined
      :to="'/articles/'+ b.slug"
      >

      <v-img
        class="white--text align-end"
        height="200px"
        src="https://cdn.vuetifyjs.com/images/cards/docks.jpg"
      >
        <v-card-title>{{b.title}}</v-card-title>
      </v-img>

      <v-card-subtitle class="pb-0">
        {{b.datetimes}}
      </v-card-subtitle>

      <v-card-text class="text--primary">
        <div>{{b.description}}</div>
      </v-card-text>

      <v-card-actions>
        <v-btn
          color="orange"
          text
        >
          Read
        </v-btn>
      </v-card-actions>
      </v-card>
      </v-col>
    </v-row>
 </v-container>  

</template>

<script>
export default {
 async asyncData ({ $content }) {
   const query = await $content('articles' || 'index').limit(20)
   const articles = await query.fetch()
   return { articles }
 }
}
</script>

記事

contents/articlesフォルダ内に、適当な名前の.mdファイルを作ります。

今回はタグ情報にこういった内容を追加しました。 markdown書く際にatomを使っていて、このプラグインを導入しています。このプラグインで新しい記事を書くと自動で挿入されるのがしたのタグです。 中身はもともとあったファイルを流用しています。

tool-bar-markdonw-writer

---
title: Getting started
date: "2021-06-03 02:19"
description: 'Empower your NuxtJS application with @nuxt/content module: write in a content/ directory and fetch your Markdown, JSON, YAML and CSV files through a MongoDB like API, acting as a Git-based Headless CMS.'
---

実行結果

ちなみに同じmarkdownファイルをコピーして増やすと記事も増えます。

まとめ

前回と同じところまでVuetify.jsを使って書き換えることができました。 道半ば感はありますが良いんじゃないでしょうか。 今日は子供が早起きなのでここまでです。