Nuxt.js と簡易 api サーバで簡単な Guestbook みたいの作ってみる


## プロジェクト作成

```
$ mkdir guestbook
$ cd guestbook
$ emacs package.json
```

```package.json
{
  "name": "guestbook",
  "scripts": {
    "dev": "nuxt"
  }
}
```

### ライブラリをインストール

```
$ npm install --save nuxt
$ npm install @nuxtjs/axios --save
```
ちなみに　`nuxt v1.0.0`（2018-01-12現在）

## 開発用簡易apiサーバに json-serverを利用

```
$ npm install json-server install -D
$ emacs db.json
```

```db.json
{
  "comments": [
    {
      "id": 1,
      "body": "Hello"
    },
    {
      "id": 2,
      "body": "Hi"
    },
    {
      "id": 3,
      "body": "yey"
    },
    {
      "id": 4,
      "body": "Yummy"
    }
  ]
}
```

### json-server起動して動作確認

```
$ node_modules/.bin/json-server --watch db.json --port 3333
```

```
$ curl http://localhost:3333/comments/
[
  {
    "id": 1,
    "body": "Hello"
  },
  {
    "id": 2,
    "body": "Hi"
  },
  {
    "id": 3,
    "body": "yey"
  },
  {
    "id": 4,
    "body": "Yummy"
  },
  {
    "body": "bowwow",
    "id": 5
  }
]%
```

## Nuxt.js でアプリ作成

### pages

```
$ mkdir pages
$ emacs pages/index.vue
```

```html:pages/index.vue
<template>
  <section class="container">
    <div>
      <logo/>
      <h1>
        Guestbook
      </h1>
      <div>
          <input @keyup.enter="addComment">
      </div>
      <ul class="comments">
          <li v-for="(comment, index) in comments">
              {{ comment.body }}
          </li>
      </ul>
    </div>
  </section>
</template>

<script>
import axios from 'axios'

const API_URLS = {
  comments_list: 'http://localhost:3333/comments/',
  create_comment: 'http://localhost:3333/comments/'
}

export default {
  async fetch ({ store, params }) {
    let { data } = await axios.get(API_URLS.comments_list)
    store.commit('comments/set', data)
  },
  computed: {
    comments () { return this.$store.state.comments.list }
  },
  methods: {
    async addComment (e) {
      const comment = e.target.value

      if (comment) {
        await axios.post(API_URLS.create_comment, { body: comment })

        e.target.value = ''

        let { data } = await axios.get(API_URLS.comments_list)
        this.$store.commit('comments/set', data)
      }
    }
  }
}
</script>

<style>
.container {
  min-height: 100vh;
  margin-top: 30px;
  display: flex;
  justify-content: center;
  text-align: center;
}
</style>
```

（styleはスターターテンプレートのものを流用）


### store

```
$ mkdir store
$ emacs store/comments.js
```

```store/comments.js
export const state = () => ({
  list: []
})

export const mutations = {
  set (state, data) {
    state.list = data
  }
}
```

## プロジェクトを起動してブラウザで表示

```
$ npm run dev
```

- http://localhost:3000/

![guestbook.gif](https://qiita-image-store.s3.amazonaws.com/0/41656/6e11d1ac-f8e7-e526-bdb9-e31ecab4f039.gif)


## ファイル構成

```
$ tree . -I node_modules
.
├── db.json
├── package-lock.json
├── package.json
├── pages
│   └── index.vue
└── store
    └── comments.js
```

## 感想

- Vue界隈は日本語のドキュメントがあるのがとてもありがたい :pray: 
- api投げる処理は何処に書くのがきれいなんだろう？
- 一見簡単そうだけどそれなりの規模のアプリ作る場合いろいろ引っかかりそうかも
- vue と vuex ほぼ初めて書いたから書き慣れてないだけかも
- vueベースが `Nuxt.js` で Reactベースが `Next.js`（名前似過ぎでちょっと分かりづらいw）
- Vue.js と React.js どちらが好きかで評価が分かれそうかも

## 参考サイト

- [Nuxt.js - ユニバーサル Vue.js アプリケーション  ](https://ja.nuxtjs.org/)
- [Vue.js](https://jp.vuejs.org/index.html)
- [Vuex 入門 · Vuex  ](https://vuex.vuejs.org/ja/getting-started.html)
- [Learn Next.js - Create SSR Enabled React Apps Easily  ](https://learnnextjs.com/)