Vue.jsによるフロントエンドの実現（ミニマム版） ~ Node.js + NoSQL(Couchbase) アプリ開発 ステップバイステップガイド (4)

# はじめに

[前回の記事](https://qiita.com/yoshiyuki_kono/items/f540f2d98f9622f28567)では、Node.js + Hapi + Couchbaseを使って、RESTサービスを構築しました。
今回は、[Vue.js](https://jp.vuejs.org/index.html)を使って、フロントエンドを構築します。

# 実装

## 環境準備

### vue-cliインストール

```
$ npm install -g vue-cli
```

```
$ vue --version
@vue/cli 4.5.9
```

### プロジェクト生成

```
$ vue init webpack <プロジェクト名>
``` 
適宜ウィザードの質問に応答して進めます（今回、自分が行った内容を参考まで付け加えれば、Linter、単体テスト、E2Eテストツールを選択しませんでした。とはいえ、その他のRouterなどについても、特に使っているわけではありません）。

ウィザード完了後、生成されたディレクトリへ移動します。

```
$ cd <プロジェクト名>
```

`package.json`中の`dependencies`として確認できるモジュールのバージョンは以下の通りです。

```json
  "dependencies": {
    "axios": "^0.21.1",
    "vue": "^2.5.2",
    "vue-router": "^3.0.1"
  },
```

## コード編集

生成されたコードを元に編集していきます。

### CSSライブラリ Bootstrap Vue 利用設定

CSSライブラリ[Bootstrap Vue](https://bootstrap-vue.org/)を利用します。
簡易的に、CDN(Content Delivery Network)を使って利用するため`index.html`を編集します。
(ここで指定しているバージョンは現時点の最新版ではありませんが、利用実績のあるものを引継ぎ、特に更新していません)


```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>User Management</title>
    <link rel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
        <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  </body>
</html>

```

### App.vueファイル編集

`src`ディレクトリの下にある`App.vue`ファイルを下記のように編集します。

```vue:App.vue
<template>
  <div id="app">
        <div class="container">
            <div class="row">
                <div class="col-md-6">
                    <div class="well">
                        <form>
                            <div class="form-group">
                                <label for="lastname">姓</label>
                                <input type="text" v-model="input.person.lastname" class="form-control" id="lastname" placeholder="Last Name">
                                <input type="hidden" name="type" value="person"> 
                            </div>
                            <div class="form-group">
                                <label for="firstname">名</label>
                                <input type="text" v-model="input.person.firstname" class="form-control" id="firstname" placeholder="First Name">
                            </div>
                            <button type="button" v-on:click="createPerson()" class="btn btn-default">Save</button>
                        </form>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <ul class="list-group">
                    </ul>
                </div>
            </div>
        </div>
        <div class="row">
                <div class="col-md-12">
                    <ul class="list-group">
                        <li v-for="(person, index) in people" class="list-group-item">
                            {{person.lastname}}　{{person.firstname}} 
                            <p>
                            </p>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
  </div>
</template>

<script>
/* eslint-disable no-console */
import axios from "axios";
export default {
  name: 'App',
data(){
            return{
                input:{
                    person:{
                        firstname:"",
                        lastname:""
                    }
                },
                people:[]
            }
        },
        mounted(){
            axios({method:"GET",url:"http://localhost:3000/users"}).then(result=>{
                this.people=result.data;
            });
        },
        methods:{
            createPerson(){
                if(this.input.person.firstname!=""&& this.input.person.lastname != "") {
                    axios({ method: "POST", url: "http://localhost:3000/user", data: this.input.person, headers: { "content-type": "application/json" }}).then(result => {
                        this.people.push(result.data);
                        this.input.person.firstname="";
                        this.input.person.lastname="";
                    });
                }
            }
        }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

## 実行確認

### サーバー起動

```
$ npm run dev
```



### サイトへのアクセス

http://localhost:8080

### アクセス結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/1c642a60-e8c7-958f-8732-a5666900f161.png)


# 最後に

ここまでの一連の記事により、特別な予備知識を前提としなくても、アプリケーションの稼働を確認するまでの、ミニマムな情報を提供できたと考えています。

私自身、（WEBアプリケーション開発の経験はありますが）ここで使ったフレームワークについては、初めて触れるものばかりでした。下記の参考情報などを参照しつつ、徒らに複雑になる要素などを取り除きながら、コードを最終化していきました。

Couchbase含め、それぞれの技術に初めて触れる方にとっても、手順通りに進めればアプリケーションの挙動を確認でき、コード自体を参照することによって行われていることについてイメージを掴むことができるものとなることを目指しました。

説明など、簡略的すぎる気味も大いにありますが、私自身、何か新しい技術に初めて触れる時、最低限の要素が整理されているとありがたいと感じるので、そのようなものとして機能すれば幸いです。

# 参考情報

[Going Full Stack with Node.js, Vue.js, and Couchbase NoSQL](https://blog.couchbase.com/full-stack-node-js-vue-js-couchbase-nosql/)