Vue.jsでTODOTrello風アプリを作る

業務でTrelloをよく使うので、Vue.jsを使って同じようなTODOアプリ作れないかなーと思い作成。
部分的に、気になるところを抽出して説明していきたいと思います。

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="reset.css">
    <link rel="stylesheet" href="style.css">

</head>

<body>

    <div id="app">
        <div class="container">

            <div class="flexitem item1">
                <h1>未着手</h1>

            </div>

            <div class="flexitem item2">
                <h1>進行中</h1>

            </div>


            <div class="flexitem item3">
                <h1>TODOリスト</h1>

            </div>

            <div class="flexitem item4">
                <h1>確認待ち</h1>

            </div>

            <div class="flexitem item5">
                <h1>完了</h1>

            </div>

        </div>
    </div>


</body>



</html>


```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499375/2af0eddc-cbe7-1064-5039-939b6e98b36a.png)

ベースはhtmlとcss(flexbox)で作りました。ここに、Vue.jsを使ってTODOリストを作成していきます。

```html

 <body> 
     <div id="app"> 
         <p><input type="text" placeholder="TODOを入力してください" v-model="newitemtitle"> 
             <button v-on:click="addbutton">add</button></p> 
  
         <ul> 
             <li v-for="(item,index) in items"> 
               <label> 
                 <label v-bind:class="{ done: item.ischecked }"> 
                 <input type="checkbox" v-model="item.ischecked"> {{ item.title }} 
                 <button v-on:click="deletebutton(index)">delete</button> 
               </label> 
             </li> 
           </ul> 
  
     </div> 
  
 </body> 
```

```js

let vm = new Vue({
  el: '#app',
  data: {
    items: [],
    newitemtitle: '',
    id:0
  },
  methods: {
    addbutton: function () {
      if (this.newitemtitle === '')
        return;
      this.items.push({
      
        title: this.newitemtitle, ischecked: false,
        id:this.id++
        
      });
      this.newitemtitle = ''
    },
    deletebutton:function(index){
      if(confirm('本当に削除しますか？')){
      this.items.splice(index,1)
      }
    }
  }
})
```
```html

 <p><input type="text" placeholder="TODOを入力してください" v-model="newitemtitle"> 
```
で、テキストボックス配置。v-modelで、vueインスタンスのdataオプションの、newitemtitleと紐づけます。
**htmlのnewitemtitleに変更があれば、紐づいているjsのnewitemtitleの値も更新されます。**
newitemtitle=' 'とすることによって、空の状態でテキストボックスを作成できます。

```html
<button v-on:click="addbutton">add</button></p>
```
で、v-on:clickディレクティブを使い、addボタンをクリックしたときに、addbuttonメソッドが呼ばれます。
下記のメソッドです。

```js
addbutton: function () {
      if (this.newitemtitle === '')
        return;
      this.items.push({

        title: this.newitemtitle, ischecked: false,
        id:this.id++

      });
      this.newitemtitle = ''
    }
```
空文字だったらreturnで処理を終了させて、pushメソッドで、配列 items[ ]の中に、テキストボックスで入力した値を追加します。値を追加すると、テキストボックスの中身が空になっていて欲しいので、

```js
this.newitemtitle = ''
```
で、配列に値を追加した後に、テキストボックスの中身を空にします。

```js
ischecked: false
```
は、

```html
<label v-bind:class="{ done: item.ischecked }">
```
と紐づいてくるのですが、ischeckedがtrueだったら、TODOに打ち消し線を引くようにCSSで調整してます。

```css
.done{
    text-decoration: line-through;
}
```


```html
<li v-for="(item,index) in items" v-bind:key="item.id">

```

```js
v-bind:key="item.id
```
配列内のデータを繰り返し表示するのに、なぜ```v-bind:key="item.id```が必要なのか....
調べたところによると、**ただ表示する分にはkeyを与えなくてもいいが、要素の追加や削除、順序変更などがある場合は、要素が意図しない動きをしてしまうため**　らしいです。今回のTODOアプリはもろ当てはまってます(汗)
各要素ごとに、一意のkeyを設定してあげることにより正しく表示できる、ということですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499375/13b00ccc-f37c-e22b-7c58-f8c19432346c.png)

一旦はそれっぽく表示できました。TODOリスト内の要素を、「進行中」や、「完了」へとドラッグ&ドロップで移動できるようにするため、Vue.Draggableというライブラリを使いました。
今回はCDNを使いました。

```html
<li v-for="(item,index) in items" v-bind:key="item.id">
```
を、

```html

<draggable tag="ul" v-bind:options="{group:'ITEMS'}">
<li v-for="(item,index) in items" v-bind:key="item.id">
</draggable>
```

このように囲ってあげると、リスト内で要素の順序変更が行えるようになります。
https://i.gyazo.com/1d49eb621ce87037b510cdb4649d4329.mp4

これ見た目だけは動いてるように見えるけど、データの保存とかどうすんだこれ・・・・


---
参考にさせていただいた記事
[Vue.jsでドラッグ＆ドロップするなら「Vue.Draggable」がおすすめ](https://www.kabanoki.net/1712/)
[Vue.js: v-forで項目インデックスをkey属性にしていいのか](https://qiita.com/FumioNonaka/items/d1d9c9335116426a8316)