【Nuxt.js】todoアプリを作成してみた①

業務でNuxt.jsを使うことになったので、定番ですが簡単なtodoアプリを作成してみました。
本で勉強していると、どの部分から実装していけば分かりにくいところもあるので、
順を追って実装できるように書いてみました。
初めてNuxt.jsを勉強する、とりあえずNuxt.jsで動くものを作ってみたい、という方の参考になると幸いです。

<h1>今回作成したアプリ</h1>
![todoapp_final.png](https://qiita-image-store.s3.amazonaws.com/0/388011/7a0274b7-77c1-5cf6-9225-c2f3f49408cd.png)
todo追加/検索/削除機能のみのシンプルなtodoアプリです。

<h1>前提</h1>
・Node.jsはインストール済（バージョンは現時点でv10.13.0）
・Vue.jsはある程度理解している
（私は<a href="https://www.amazon.co.jp/Vue-js-Nuxt-js%E8%B6%85%E5%85%A5%E9%96%80-%E6%8E%8C%E7%94%B0%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798056596">Vue.js & Nuxt.js超入門</a>で勉強していました）

<h1>作成の手順</h1>
(1)Nuxt.jsのプロジェクト作成
(2)template作成
(3)store作成
(4)追加機能作成
(5)検索機能作成
(6)削除機能作成
(7)cssファイル作成

この記事では(1)〜(3)、次回の記事で(4)以降について書きます。

<h1>(1)Nuxt.jsのプロジェクト作成</h1>
<a href="https://ja.nuxtjs.org/guide/">公式サイト</a>に書いてある通り、Nuxt.jsはVueアプリケーションを作成するフレームワークです。
todoアプリ作成にあたり、まずはNuxt.jsのプロジェクトを作成します。
プロジェクトを作成したいディレクトリに移動し、以下のコマンドを実行します。
私はDesktopにpracticeというフォルダを作って、そこにsample-todo-appという名前のプロジェクトを作成しました。

```ターミナル
$ cd Desktop/practice
$ npx create-nuxt-app sample-todo-app
```

ProjectNameなど確認する表示が出てきますが、初期設定のままEnterを押していって大丈夫です。
AutherNameは自分の名前のローマ字など適当に入力してください。

installが完了したら、以下のように作成したプロジェクトに移動して実行します。

```ターミナル
$ cd sample-todo-app
$ npm run dev
```

localhost:3000にアクセスして、以下の画面になっていればプロジェクトの作成は完了です。
![project_first.png](https://qiita-image-store.s3.amazonaws.com/0/388011/ec56a110-2c37-a567-5f00-475c3b166d4a.png)

<h1>(2)template作成</h1>
作成したプロジェクトのpagesフォルダのindex.vueファイルを開いて、template部分を作成します。

```vue:pages/index.vue
<template>
  <section class="container">
    <h1>Todo App</h1>
    <p><input type="text" name="content"/></p>
    <div>
      <button>save</button>
      <button>find</button>
    </div>
    <ul>
      <li>
        <span>hogehoge</span><span>(2019-03-31 15:00)</span><span>×</span>
      </li>
    </ul>
  </section>
</template>

<script>
</script>
```

![(2)sample.png](https://qiita-image-store.s3.amazonaws.com/0/388011/f83876c1-1bb9-ec31-dd07-04df5a22ca91.png)
listの部分は一旦仮でテキストを入力しています。

<h1>(3)store作成</h1>
続いてstoreを作成していきます。
storeフォルダの中に、index.jsという名前のファイルを作成し、以下のようにコードを書いていきます。

```js:store/index.js
import Vuex from 'vuex';

const createStore = () => {
    return new Vuex.Store({
        state: () => ({
            todos: [
                {content: 'hogehoge', created: '2019-03-31 15:30'}, 
                {content: 'fugafuga', created: '2019-03-31 16:00'}
            ]
        }),
        mutations: {
            insert: function(state, obj) {
                var d = new Date();
                var fmt = d.getFullYear() 
                            + '-' + ('00' + (d.getMonth() + 1)).slice(-2) 
                            + '-' + ('00' + d.getDate()).slice(-2) 
                            + ' ' + ('00' + d.getHours()).slice(-2) 
                            + ':' + ('00' + d.getMinutes()).slice(-2);
                state.todos.unshift({
                    content: obj.content,
                    created: fmt
                })
            },
            remove: function(state, obj) {
                for(let i = 0; i < state.todos.length; i++) {
                    const ob = state.todos[i];
                    if(ob.content == obj.content && ob.created == obj.created) {
                        alert('remove ' + '"' + ob.content + '"');
                        state.todos.splice(i, 1);
                        return;
                    }
                }
            }
        }
    })
}

export default createStore;
```

<h3>Vuexとは？</h3>
<a href="https://vuex.vuejs.org/ja/">Vuex</a>はVue.jsアプリケーションのための状態管理パターン+ライブラリです。
Nuxt.jsでは表示するページをそれぞれvueファイルとして作成しますが、すべてのページで利用するデータをまとめて保管するための仕組みがVuexです。
コンポーネントからVuexの変数や処理を利用するために$storeという値が用意されていて、その中から値などを取り出すことができます。

<h3>stateの中身</h3>
todosという配列を設定し、この中にtodoを追加したり削除したりします。
todoには、todoの内容(content)とtodoが追加された日時（created）の2つのプロパティを持たせます。
（一旦仮で2つ、todoを設定しています。）

<h3>mutationsの中身</h3>
stateの値を変更するための処理をmutationsの中に書きます。

1つめのinsertでは、state（todos）と入力されたtodoを引数として、
入力されたtodoと入力された時間（fmt）を配列todosに追加します。

2つめのremoveでは、insertと同じくstate（todos）と入力されたtodoを引数として、
入力されたtodoの内容と日時が配列todosのtodoと一致した場合に、
「remove (todoの内容)」というalertを表示させ、配列todosから削除します。

<h3>todosの表示</h3>

ここまでできたらtodosを表示させてみます。
pagesフォルダのindex.vueを以下のように修正します。

```vue:pages/index.vue
<template>
  <section class="container">
    <h1>Todo App</h1>
    <p><input type="text" name="content"/></p>
    <div>
      <button>save</button>
      <button>find</button>
    </div>
    <ul>
      <li v-for="(todo, index) in todos" :key="index">
        <span>{{ todo.content }}</span><span>({{ todo.created }})</span><span>×</span>
      </li>
    </ul>
  </section>
</template>

<script>
import {mapState} from 'vuex';

export default {
  data: function() {
    return {
      content: ''
    }
  },
  computed: {
    ...mapState(['todos'])
  }
}
</script>
```

![(3)sample.png](https://qiita-image-store.s3.amazonaws.com/0/388011/b59fbe62-e339-9359-8690-acfd1318e810.png)
mapStateを使うことで、scriptの中ではthis.`stateの名前`、templateでは{{`stateの名前`}}でstateの値を利用することができます。
（もしエラーが表示される場合は、再起動してからもう一度localhost:3000にアクセスしてみてください）

<h1>おわりに</h1>
ここまで、Nuxt.jsでのプロジェクト作成、storeからのデータ利用を中心に説明してきました。
次回、追加/検索/削除機能を実装していきます。

<a href="https://qiita.com/ayapon/items/31b44a43cac73f29f811">【Nuxt.js】todoアプリを作成してみた②</a>

<h1>参考</h1>
<a href="https://www.amazon.co.jp/Vue-js-Nuxt-js%E8%B6%85%E5%85%A5%E9%96%80-%E6%8E%8C%E7%94%B0%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798056596">Vue.js & Nuxt.js超入門</a>