『Nuxt.jsを使ってTodoリストを作ってみる』をやってみる

## はじめに

- タイトル通り[こちら](https://www.boel.co.jp/tips/vol107/)のチュートリアルをやってみる。というやつです。
- チュートリアルをやっていて『これ、直感に反するな..』とか、『なにそれ？どういう意味??』みたいに感じたところを補完していきます。
- 加えて、SPAとしてGithub Pagesにデプロイ、一部リファクタリングも行っています。
- とりあえず、nuxtを使ってtodoアプリを作りたい人、チュートリアルをこれからやるという人、チュートリアル中に頭がごちゃごちゃしてしまった人、同チュートリアルが終了済みでデプロイもしてみたいという人に参照してもらえるとうれしいです。



## 環境

- ubuntu



## node.jsのインストール

- ここは解説がされていませんでした。
- 最新安定板を入れるには次の記事がいまだに使えます。https://qiita.com/seibe/items/36cef7df85fe2cefa3ea
- LTS版が準備できました

```
$ node -v
v16.14.0
```

- ついでにcreate-nuxt-appも用意します

```
$ npm install create-nuxt-app
$ npm view create-nuxt-app version
4.0.0
```



## Nuxt.jsのインストール・プロジェクトの作成

- プロジェクト作成時にいくつか質問があるのですが、チュートリアルとは若干順番が変わっていました。しかし特に問題はありません。追加された質問3つでした。
- (1)Linting tools, (2)Deployment target, (3)What is your GitHub username?
- (1)と(2)は任意でよいでしょう。(2)は、静的ホスティングかサーバホスティングかを答えるのですが、GithubPagesにデプロイするためにStaticとしました。



## ひな型作成

- 画像のようにスタイリングはされていませんが、今回はVue.js、nuxt.jsの開発の流れを理解するのが目的なので割愛します。
- この章は特に問題はありませんでした。



## Vuexストアの作成

- Vuexストアを定義しています。ポイントとしてstateはオブジェクトを返すアロー関数として定義しているところでしょうか。

- それから、最後のexport defaultについて、

  ```javascript
  export default createStore;
  ```

  - JavaScriptではexportに2種類あり、名前付きエクスポートと、デフォルトエクスポートがあります。デフォルトエクスポートではインポートするときに自由に名前を変えることができます。

  - 名前付きエクスポートの例です。

  ```javascript
  // 定義済みの関数や変数をエクスポート
  export myFunction;
   
  // 利用する別のモジュールでは以下のようにインポートする
  import myFunction from './my-module.js';
  ```

  - デフォルトエクスポート

  ```JavaScript
  // 定義済みの関数や変数をエクスポート
  export default myFunction;
  
  // 利用する別のモジュールでは以下のようにインポートする。(mfという名前でimportできる！)
  import mF from './my-module.js';
  ```

  - ただし、デフォルトエクスポートは１モジュールに対して１つだけとなっていいます。
  - [ES6のexportについて詳しく調べた](https://qiita.com/senou/items/a2f7a0f717d8aadabbf7)でより詳しい情報が載っています。

- また、pages/index.vueのscript部分ですが一部抜けていました。

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

  export default {
    data: function() {
      return {
        content:'' ＃ここの''が抜けていました。
      }
    },
    computed: {
      ...mapState(['todos'])
    }
  }
</script>
```

- Vuexストアのtodos配列をmapStateにいれて展開しています。ここでは、computed(算出プロパティ)にtodosを登録することで値を監視し、変更されたときに自動で再描画するように動くわけです。



## 「タスクの削除」機能の実装

- 特に問題はありませんでした。
- Vuexストアのmutationsの中のinsertでは、unshiftを使っています。unshiftは配列の始めに値を挿入するメソッドです。



## 「タスクの削除」機能の実装

- こちらもタスクの追加機能の応用で作れますね。問題なく動きました。



## 「タスクの状態変更」機能の実装

- 全体的に複雑になっいるのでぼくのほうで詳しく解説したいと思います。

- この章でのゴールは、状態ボタンを押して作業前->作業中->完了というタスクの状態をラウンドロビン方式で変更できるようにすることです。

- それを実現するには

  1. ボタンにクリックイベントを仕込みchangeStateを発火させる

  2. changeStateからVuexストアにあるchangeStateを呼び出す
  3. VuexストアのchangeStateで値を更新する仕組みをつくる

- このように見ていくと、実際に値の更新の行っているコードは、Vuexストア内で完結しているので、関心が分離されいいてすっきりした印象がします。

- さて、Vuexストアの内部にあるのが次のコードです。

```javascript
changeState: function(state, obj) {
  for (let i = 0; i < state.todos.length; i++) {
    const ob = state.todos[i];　// 1
    if(ob.content == obj.content && ob.created == obj.created && ob.state == obj.state) {
      let nowState; // 2
      for(let j = 0; j < state.option.length; j++){
        if(state.option[j].label == ob.state){
          nowState = state.option[j].id;
        }
      }
      nowState++; // 3
      if(nowState >= state.option.length){
        nowState = 0;
      }
      obj.state = state.option[nowState].label
      return;
    }
  }
}
｝｝
```

- こちらもステップに分解していくと

  1. 引数のobjから同値のtodoを取り出す
  2. 現在のtodo.stateを取り出し
  3. todo.stateに１を足す

  と整理できます。ネストが必要以上に深いので、ぼくの方でリファクタリングしてみました。さらにやるならtodoデータにidをつけたほうがよさそうですね。

```javascript
 changeState: function(state, obj) {
     // 1 引数のobjから同値のtodoを取り出す
     let todo = null
     for (let i = 0; i < state.todos.length; i++) {
         let ob = state.todos[i];
         if(ob.content == obj.content && ob.created == obj.created && ob.state == obj.state) {
             todo = obj
         }
     }
     // 2 現在のtodo.stateを取り出し
     let nowState;
     for(let j = 0; j < state.option.length; j++){
         if(state.option[j].label == todo.state){
             nowState = state.option[j].id;
         }
     }
     // 3 todo.stateに１を足す
     nowState = (nowState+1) % state.option.length;
     todo.state = state.option[nowState].label
     return;
 }
```



## 「絞り込み」機能の実装

- こちらも複雑なのでぼくのほうで説明してみたいと思います。

- こちらの章のゴールは、追加フォームの下の4つのボタンをクリックしたら、todoを状態(todo.state)でフィルタリングし、一覧表示を再描画できるようにすることです。

- それを実現するには

  1. 各ボタンにクリックイベントを設置し、findメソッドを発火させます。
  2. findメソッドでは、データプロパティのfind_flg find_stateの値を書き換えます。
  3. todosをそのままリスト表示するのではなく、前段に算出プロパティ(computed)のdisplay_todosを追加して出力するデータを制御しています。find_flgが立っているならフィルターされた値、そうではないならtodosをそのまま出力しています。

- 1,2については先ほどから行っている方法ですのでよいでしょう。

- 3,では算出プロパティを使っていますが、これを使うことによってdisplay_todos関数はデータプロパティのfin_flg, find_stateに依存していることを知っているので、これらが書き換えられると自動で再描画するように動くというわけです。 

- methodやwatchプロパティでも良いのでしょうが、computedが一番冗長にならず[パフォーマンス](https://jp.vuejs.org/v2/guide/computed.html#%E7%AE%97%E5%87%BA%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3-vs-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)もよいです。

- また、1について、具体的にはこんなコードでした

  ```javascript
  <button class="button button--gray" v-bind:class="{'is-active':find_flg && (find_state == '作業前')}" @click="find('作業前')">作業前</button>
  ```

  - ぼくはスタイリングをしていないのでis-activeを計算してもしょうがないのですが、このようにインラインで書くには少し長いような気がします。以下のようにcomputedしてもよいかと思います。waitingは作業前のリストということを意味しています。

  ```
  <button :class="waiting_state_active" @click="find('作業前')">作業前</button>
  .
  .
  
  computed: {
  	...
       waiting_state_active: function() {
         return this.find_flg && (this.find_state == '作業前')
       }
  },
  ```



## Github Pagesにデプロイする

- [こちら](https://zenn.dev/catch/articles/install_nuxtjs)を参考にしてデプロイをしてみます。
- 前提として、public repositoryであれば無料でデプロイが可能です。リポジトリの/(root)か/docsというフォルダーをデプロイすることができます。手順は以下の通りです。
  1. nuxt.jsのビルド先をdocsに変更してからビルドする。
  2. Githubにpushし、pagesの設定をする。

1. nuxt.config.jsに以下のように追加する。

   ```javascript
     router: {
       base: '/リポジトリの名前/'
     },
   
     generate: {
       dir: 'docs'
     },
   }
   ```

   ビルドする

   ```
   $ npm run generate
   ```

2. nuxt.config.jsと生成したdocsフォルダをコミットしてGithubにPushしてください。
   それから、Settings ＞pagesに行ってSourceの

   - Branchにmain
   - フォルダに/docs

   を追加してsave!

   ```
   Your site is ready to be published at https://...
   ```

   と出るのでリンクをクリックすると！　なんと！！
   無事に公開されています！！！



以上です。ありがとうございました。



## 参考資料

[Nuxt.jsを使ってTodoリストを作ってみる](https://www.boel.co.jp/tips/vol107/)
[Ubuntuに最新のNode.jsを難なくインストールする](https://qiita.com/seibe/items/36cef7df85fe2cefa3ea)
[ES6のexportについて詳しく調べた](https://qiita.com/senou/items/a2f7a0f717d8aadabbf7)
[クラスとスタイルのバインディング](https://jp.vuejs.org/v2/guide/class-and-style.html)