LoginSignup
29
48

More than 3 years have passed since last update.

Vue.jsで作るtodoアプリ

Last updated at Posted at 2020-05-03

Vue.jsで作るtodoアプリ

前回の記事はこちら
Vue.js ディレクティブの基礎2

これまで紹介したディレクティブを使って
簡単なtodoアプリを作ってみましょう。
jsfiddleで実際に記述しながら読むことをおすすめします。
下記が完成品です。

Image from Gyazo

ページのリロードをせずにタスクの追加・完了・削除ができよう実装します。
※タスクの保存はしない仕様とします。

空のVueインスタンスとテンプレートの作成

まずはhtmlとjsシートに下記を準備します。
jsfiddleを使用してコード部分のみ記述します。

index/html
<div id="app">

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
index.js
var app = new Vue({
    el:'#app',

})

要素の配置とイベントハンドリング

index/html
<div id="app">
<h2>TODO List</h2>

<form v-on:submit.prevent>
  <input type="text">
  <button v-on:click="addItem">Add</button>
</form>

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
index.js
var app = new Vue({
  el:'#app',
  methods:{
    addItem:function(event){
      alert();
    }
  }
})

Image from Gyazo

デバッグのためにalertを記述して動作確認します。
alertダイアログが表示されます。

formのsubmitイベントでページのリロードを無効にするため
formタグにイベント修飾子preventを追記しておきましょう。

inputタグの中身を双方向データバインディングする

index/html
<div id="app">
<h2>TODO List</h2>

<form v-on:submit.prevent>
  <input type="text" v-model="newItem">
  <button v-on:click="addItem">Add</button>
</form>

<pre>{{ $data }}</pre>

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
index.js
var app = new Vue({
  el:'#app',
  data:{
    newItem:""
  },
  methods:{
    addItem:function(event){
    alert();
    }
  }
})

Image from Gyazo

v-modelディレクティブでinputタグの中身をバインディングします。
デバッグ用にpreタグを使用してdataオプションの中身を確認しましょう。

タスクの追加

次に空の配列を用意しAddボタンのクリックイベントで
タスクを配列に格納していきます。

index/html
<div id="app">
<h2>TODO List</h2>

<form v-on:submit.prevent>
  <input type="text" v-model="newItem">
  <button v-on:click="addItem">Add</button>
</form>

<pre>{{ $data }}</pre>

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
index.js
var app = new Vue({
  el:'#app',
  data:{
    newItem:"",
    todos:[]
  },
  methods:{
    addItem:function(event){
      //alert();
      if(this.newItem == '')return; //タスク未入力の場合は追加しない
      var todo = {
        item: this.newItem
      };
      this.todos.push(todo);
      this.newItem = '' //タスク追加後に入力欄を空にする
    }
  }
})

Image from Gyazo

dataオプションに空の配列todosを作成し
addItemメソッド内でinputタグの中身を
todoとして取得してtodosの配列へ格納しています。

task入力後にinput欄をクリアしておきましょう。
合わせてタスク未入力の場合は追加ができないようif文を記述しましょう。

タスクのリスト表示

index/html
<div id="app">
<h2>TODO List</h2>

<form v-on:submit.prevent>
  <input type="text" v-model="newItem">
  <button v-on:click="addItem">Add</button>
</form>

<ul>
  <li v-for="todo in todos">{{todo.item}}</li> <!--配列の中身を1つずつ取得-->
</ul>

<pre>{{ $data }}</pre>

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
index.js
var app = new Vue({
  el:'#app',
  data:{
    newItem:"",
    todos:[]
  },
  methods:{
    addItem:function(event){
    //alert();
    if(this.newItem == '')return;
    var todo = {
      item: this.newItem
    };
    this.todos.push(todo);
    this.newItem = ''
    }
  }
})

Image from Gyazo

v-forディレクティブをliタグに設定して配列の中身を取得します。

タスクの管理とスタイルの設定

index/html
<div id="app">
<h2>TODO List</h2>

<form v-on:submit.prevent>
  <input type="text" v-model="newItem">
  <button v-on:click="addItem">Add</button>
</form>

<ul>
  <li v-for="todo in todos">
  <input type="checkbox" v-model="todo.isDone"><!--チェックボックス同期-->
  <span v-bind:class="{done: todo.isDone}">{{todo.item}}</span><!--classの追加-->
  </li>
</ul>

<pre>{{ $data }}</pre>

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
index.js
var app = new Vue({
  el:'#app',
  data:{
    newItem:"",
    todos:[]
  },
  methods:{
    addItem:function(event){
      //alert();
      if(this.newItem == '')return;
      var todo = {
        item: this.newItem,
        isDone:false
      };
      this.todos.push(todo);
      this.newItem = ''
    }
  }
})
index.css
#app ul{
  list-style:none;
}

#app li > span.done{
  text-decoration:line-through;
}

Image from Gyazo

タスクにチェックボックスを設定しv-modelディレクティブで
ステータスをisDoneと同期します。

isDoneのステータスによってclassが付与されるよう
v-bindディレクティブでclassをバインディングしましょう。

classの付与によって打ち消し線が表示されるようCSSを記述しました。

タスクの削除

index/html
<div id="app">
<h2>TODO List</h2>

<form v-on:submit.prevent>
  <input type="text" v-model="newItem">
  <button v-on:click="addItem">Add</button>
</form>

<ul>
  <li v-for="(todo,index) in todos"> <!--indexを引数に追加-->
  <input type="checkbox" v-model="todo.isDone">
  <span v-bind:class="{done: todo.isDone}">{{todo.item}}</span>
  <button v-on:click="deleteItem(index)">Delete</button> <!--indexを引数に指定-->
  </li>
</ul>

<pre>{{ $data }}</pre>

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
index.js
var app = new Vue({
  el:'#app',
  data:{
    newItem:"",
    todos:[]
  },
  methods:{
    addItem:function(event){
      if(this.newItem == '')return;
      var todo = {
        item: this.newItem,
        isDone:false
      };
      this.todos.push(todo);
      this.newItem = ''
    },
    deleteItem:function(index){ //indexを引数に指定
      this.todos.splice(index,1) //indexで指定された要素を1つ削除
    }
  }
})

Image from Gyazo

以上でtodoアプリは完成となります。
タスクの追加、完了、削除の動作確認をして
問題なければデバッグ用のpreタグを消しておきましょう。

次回はテンプレート構文です。
Vue.jsテンプレート構文

29
48
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
48