18
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TechCommitAdvent Calendar 2019

Day 11

Vue.js + Firebase を用いてポートフォリオ作ってみた

Posted at

※ 本投稿はTechCommit Advent Calendar 2019 11日目の記事です。

はじめに

普段はWeb製作会社でコーダーのアルバイトをしている大学4回生です。内定先の会社でVue.jsを使っているということもあり、Vue.jsで簡単に何か作成してみようと思いポートフォリオを作成しました。

今回はVue.js + Vuetify + Vue Router を用いてSPAのポートフォリオを作成し、Firebaseにホスティングしたのでその流れ等について書いています!

実際に作成したポートフォリオ
https://vue-portfolio-25939.firebaseapp.com

無題のプレゼンテーション.jpg
無題のプレゼンテーション (1).jpg

環境

  • Vue CLI v4.1.1
  • Node.js v12.6.0
  • npm v6.9.0

ポートフォリオを作成する前に考えたこと

何を掲載するか


- トップページ
- 簡単な自己紹介
- 作品
- スキル
- お問い合わせ

ざっとこんな感じで構成することにしました。

Vue.jsでどのようなものが作れるかを確認

「Vue.js ポートフォリオ」で検索すると多くの記事が出てくるので、それを一通り読みました。


参考になった記事

デザインを考える

Cacooというサービスを使って簡単にワイヤーフレームを作ってみました。

シート6枚までは無料で使えるので今回作成するポートフォリオのようにページ数の少ないコンテンツであれば無料枠でも充分です。

実際に作成した簡単なワイヤーフレーム
PC
スクリーンショット 2019-11-10 9.08.44.png

SP
スクリーンショット 2019-11-10 9.31.26.png

実装していくと「やっぱりここをこういう風にしたい」と思ったりもして、多少変更しました。

##実際にポートフォリオを作成していく

仕様

  • デザインはVuetifyを使用
  • SPA構築(Vue Router)
  • テキストアニメーション
  • モーダルウィンドウ
  • お問い合わせフォーム(Firebase Functionsを用いてメールフォーム作成)
  • アイコンはfont-awesomeを使用

Vuetify + Vue Router

vue add vuetifyでvuetifyを追加、モードはDefaultを選択。
Vue Routerに関しては、vue create時にRouterを選択し、vue-routerを使えるようにしました。

src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Top from '@/components/Top'
import Profile from '@/components/Profile'
import Work from '@/components/Work'
import Skill from '@/components/Skill'
import ContactForm from '@/components/ContactForm'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    component: Top
  },
  {
    path: '/profile',
    component: Profile
  },
  {
    path: '/works',
    component: Work
  },
  {
    path: '/skills',
    component: Skill
  },
  {
    path: '/contact',
    component: ContactForm
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

src/main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import vuetify from './plugins/vuetify';
import '@fortawesome/fontawesome-free/css/all.css'

Vue.config.productionTip = false

new Vue({
  router,
  vuetify,
  render: h => h(App)
}).$mount('#app')

単一ファイルコンポーネントを用いての実装だったので、App.vueには以下のように記述。

src/App.vue
<template>
  <v-app>
    <v-content>
      <header-menu></header-menu>
      <router-view/>
    </v-content>
  </v-app>
</template>

<script>
import HeaderMenu from './components/HeaderMenu';

export default {
  name: 'App',

  components: {
    HeaderMenu,
  },

  data: () => ({
    //
  }),
};
</script>

ちなみにヘッダーメニュー部分は以下のような感じです。hidden-sm-and-downhidden-md-and-upをクラスに付与することにより、smサイズの時にテキストを隠し、アイコンを表示。mdサイズの時にアイコンを隠し、テキストを表示させています。

src/components/HeaderMenu.vue
<template>
  <v-toolbar
    color="teal"
    dark
    class="d-flex justify-center"
  >
    <v-toolbar-items v-for="(item, index) in items" :key="index">
        <v-btn text class="hidden-sm-and-down">
          <router-link v-bind:to="item.path">
            {{ item.title }}
          </router-link>
        </v-btn>

        <v-btn text class="hidden-md-and-up">
          <router-link v-bind:to="item.path">
            <v-icon medium>{{ item.icon }}</v-icon>
          </router-link>
        </v-btn>
    </v-toolbar-items>
  </v-toolbar>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {
      items: [
        {
          title: 'トップ',
          icon: 'fas fa-home',
          path: '/'
        },
        {
          title: 'プロフィール',
          icon: 'far fa-id-badge',
          path: '/profile'
        },
        {
          title: '作品',
          icon: 'fas fa-folder',
          path: '/works'
        },
        {
          title: 'スキル',
          icon: 'fas fa-code',
          path: '/skills'
        },
        {
          title: 'お問い合わせ',
          icon: 'far fa-envelope',
          path: '/contact'
        }
      ]
    }
  }
}
</script>

お問い合わせフォーム

送信サーバとしてgmailを使うため、環境変数に以下を追加

$ firebase functions:config:set gmail.email="gmailID" gmail.password="gmailPassword" admin.email="adminAddress"

バリデーションはv-text-fieldのrulesオプションを使って実装しました。

ContactForm.vue
(略)

<v-text-field
  v-model="contactForm.name"
  :rules="contactFormValidation.nameRules"
  label="名前"
  required
></v-text-field>

(略)
<script>
import { functions } from '@/plugins/firebase'

export default {
    data: () => ({
      contactForm: {
        name: '',
      },
      contactFormValidation: {
        valid: false,
        nameRules: [v => !!v || '名前は必須項目です'],
      },
    })
}
</script>
(略)

ビルドとデプロイ

npm run buildでビルドし、firebase deployでデプロイ完了です!

まとめ

今回は初めて、vue.jsを用いてポートフォリオを作成しました。今後はサーバーサイドと連携させたものを作りたいと思っています!

間違っているところなどありましたら、コメントで教えていただけると幸いです。

18
39
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
18
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?