Vue.jsで、SPAのToDoアプリを作成してみた
はじめに
この本を参考にして、Vue.jsで、SPA(Single Page Application)のToDoアプリを作ってみました。
今回作成したもの
See the Pen Untitled by Shibata Hiroki (@khiro-enginner) on CodePen.
動き
- することを入力して「追加」を押すと、ToDoリストが表示される
- ToDoリストにチェックを入れると、取り消し線が表示され、処理済み件数が増える
- 「処理済みを削除」を押すと、取り消し線がついているToDoが削除される
ソースコード
HTML・JavaScript(JS)・CSSが関連し合って、ToDoアプリが実現しています。
HTML
headタグ内で、3系のvue.jsを読み込んでいます。
// 省略
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
// 省略
以下のような中身を書いています。
See the Pen Untitled by Shibata Hiroki (@khiro-enginner) on CodePen.
JS
Vue.jsは以下のように記述しています。
See the Pen Untitled by Shibata Hiroki (@khiro-enginner) on CodePen.
CSS
CSSで見た目を調整しています。
See the Pen Untitled by Shibata Hiroki (@khiro-enginner) on CodePen.
することを追加する機能
See the Pen Untitled by Shibata Hiroki (@khiro-enginner) on CodePen.
具体例
例えば、「食材を購入する」というToDoを「すること」に入力して「追加」を押すと、入力した文字が消え、入力欄の下に「食材を購入する」というToDoが追加されます。そして、全体の件数が1増えます。
また、「メルカリで出品する」というような2つ目のToDoを追加することもできます(いくらでも追加できます)。
このように、することを追加する 機能について見ていきます。
文字を入力したとき
文字を入力すると、入力した文字が、v-model.trim="addtext"
によって、addtext
という変数に入ります。trimがあるので、空白は取り除かれます。
<input class="todo__input" type="text" v-model.trim="addtext" placeholder="すること">
addtext
は、data関数として、最初は空白の状態で定義されています。
data() {
return {
addtext: "",
todos: []
};
},
入力欄に「食材を購入する」と入力したときには、addtext="食材を購入する"
となります。
追加ボタンを押したとき
「追加」ボタンを押すと、v-on:click="addToDo"
によって、addToDo
という関数が実行されます。
<button v-on:click="addToDo">追加</button>
addToDo
は、メソッドとして定義されています。もし addtext
があれば、todos
に { done: false, text: this.addtext }
を追加して、addtext
を空にするという処理です。
methods: {
addToDo: function () {
if (this.addtext) {
this.todos.push({ done: false, text: this.addtext });
this.addtext = "";
}
},
cleanToDo: function () {
this.todos = this.todos.filter(function (val) {
return val.done == false;
});
}
}
入力欄に「食材を購入する」と入力した状態で「追加」ボタンを押すと、todos = [ { done: false, text: "食材を購入する" } ] となります。
そして、入力欄が空になります。
ToDoが表示される
v-for="todo in todos"
によって、 { done: false, text: this.addtext }
が todo
として一つひとつ取り出されます。{{todo.text}}
で、textの中身が表示されます。
<div class="todo__list" v-for="todo in todos">
<label class="todo__label">
<input class="todo__checkbox" type="checkbox" v-model="todo.done">
<span v-bind:class="{donestyle:todo.done}">{{todo.text}}</span>
</label>
</div>
todos = [ { done: false, text: "食材を購入する" } ]
の場合、配列の中身が一つだけなので、上記HTMLが一度だけ表示されます。{{todo.text}}
の部分では、「食材を購入する」が表示されます。
todos = [ { done: false, text: "食材を購入する" },
の場合、配列の中身が二つなので、上記HTMLが2回繰り返し表示されます。{ done: false, text: "メルカリで出品する" }
] {{todo.text}}
の部分では、1回目は「食材を購入する」、2回目は「メルカリで出品する」が表示されます。
全体の件数を数えて表示させる
{{ todos.length }}
では、lengthによってtodosの中身の数を数えて表示させています。
<p>{{ remaining }} / {{ todos.length }}件処理</p>
チェックを入れた後の処理
See the Pen Untitled by Shibata Hiroki (@khiro-enginner) on CodePen.
具体例
食材を購入するというToDoを追加した後に、チェックボックスにチェックを入れると、完了済の見た目になります。また、処理済みの件数が1増えます。
このようにチェックを入れた後の処理について見ていきます。
完了済の見た目になる理由
todo
は { done: false, text: this.addtext }
というオブジェクトを持っています。
ここで注目すべきなのは、done: false
という部分です。
doneというキーは、v-model="todo.done"
によってチェックボックスに紐づけられています。そのため、チェックボックスにチェックを入れると、done: true
になります。
<input type="checkbox" v-model="todo.done">
v-bind:class="{donestyle:todo.done}"
では、テキストのspan要素に donestyle
というクラス名をつけるかどうかが決められています。最初は todo
の done
が false
なので、donestyle
が付いていません。チェックボックスにチェックを入れると、done
が true
になるので、donestyle
が追加されます。
<span v-bind:class="{donestyle:todo.done}">{{todo.text}}</span>
donestyle
は、CSSで定義されています。
.donestyle {
text-decoration: line-through;
color: lightgray;
}
よって、donestyle
が追加されると以下のような完了済の見た目になります。
処理済の件数が1件増える理由
処理済の件数は、{{ remaining }}
という部分で表示させています。
<p>{{ remaining }} / {{ todos.length }}件処理</p>
この remaining は、算出プロパティで定義されています。
computed: {
remaining: function () {
return this.todos.filter(function (val) {
return val.done == true;
}).length;
}
},
todos
の done
の値が true
のオブジェクトを filter
でフィルターにかけた後、length
で数を取得しています。
チェックボックスにチェックを入れると、done
が true
になるので、remaining
が返す数が1増えます。
todos = [ { done: false, text: "食材を購入する" } ]
の場合、チェックを入れると、todos = [ { done: true, text: "食材を購入する" } ]
になり、filter で { done: true, text: "食材を購入する" }
が抽出され、その数を length
で取得するので、remaining
が返す値は1となります。
処理済みToDoを削除する機能
See the Pen Untitled by Shibata Hiroki (@khiro-enginner) on CodePen.
具体例
「食材を購入する」を追加して、チェックを入れた後に、「処理済を削除」をクリックすると、「食材を購入する」が削除され、ToDoの件数が変化します。
これについて見ていきます。
処理済みを削除を押したとき
v-on:click="cleanToDo"
によって、処理済みを削除をクリックすると、cleanToDo
という関数が発火します。
<p><button v-on:click="cleanToDo">処理済みを削除</button></p>
cleanToDo
は、以下のように定義されています。todos
に対して filter
をかけて、done
が false
のオブジェクトを抽出して、もう一度 todos
に入れ直しています。
methods: {
cleanToDo: function () {
this.todos = this.todos.filter(function (val) {
return val.done == false;
});
}
}
todos = [ { done: false, text: "食材を購入する" } ]
の場合、チェックを入れると、todos = [ { done: ture, text: "食材を購入する" } ]
になります。filter
をかけると、done
が false
のオブジェクトが存在しないため、todos = []
となります。
ToDoが削除される理由
ToDoは以下のように表示されていました。
<div class="todo__list" v-for="todo in todos">
<label class="todo__label">
<input class="todo__checkbox" type="checkbox" v-model="todo.done">
<span v-bind:class="{donestyle:todo.done}">{{todo.text}}</span>
</label>
</div>
todos = []
の場合、配列の中身が一つもないので、上記HTMLは表示されません。
ToDoの件数が変化する理由
remaining
では残りの件数を、todos.length
では全体の件数を表示させていました。
<p>{{ remaining }} / {{ todos.length }}件処理</p>
remaing
は以下のように定義されていました。todos
で done
が ture
のオブジェクトが1件減るので、remaing
が返す値も1減ります。
computed: {
remaining: function () {
return this.todos.filter(function (val) {
return val.done == true;
}).length;
}
},
todos = []
の場合、配列の中身が一つもないので、todos.length
は0となります。
コメントを残す