Vue.jsの勉強で超簡単なタスク管理アプリを作ってみる
はじめに
現在、個人的にVue.jsを勉強しております。
個人ブログの方に、経過はまとめております。
(まだ基本文法くらいですが。。。)
Vue.js入門その1〜基本文法〜
Vue.js入門その2〜Vueインスタンスってなんぞ?〜
ただ、私がJSフレームワークの経験がないためだと思いますが、いまひとつピンとこなかったので、よくあるTODOアプリを作成してみました。
同様に勉強している方の参考になれば嬉しく思います。
サンプルはこちらです。(7/12 リンクを差し替えました)
https://jsfiddle.net/naoki85/fo26rmr0/12/
JS Fiddleを使用しているので、Vue.jsのバージョンは 2.2.1 になります。
準備
External ResourcesにてBootstrapを読み込み
CSSは面倒なので、Bootstrapを使用したいと思います。
CDNのURLを取得し、JS Fiddleの左側、External Resourcesに入力しておきます。
このとき、BootstrapのJSはJQueryを必要とするのでCSSのみにしておきます。
(後でコンソールでエラーが出てしまうので。。。)
目標のかたちをモック作成
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Studying JavaScript</td>
<td>
<div class="btn btn-danger">Done!</div>
</td>
</tr>
<tr>
<td>Studying PHP</td>
<td>
<div class="btn btn-danger">Done!</div>
</td>
</tr>
<tr>
<td>Studying Ruby</td>
<td>
<div class="btn btn-danger">Done!</div>
</td>
</tr>
<tr>
<td><input class="form-control"></td>
<td>
<div class="btn btn-default">Create Task</div>
</td>
</tr>
</tbody>
</table>
タスクの一覧表示
Vueインスタンスの作成
var vm = new Vue({
el: '#tasks-index',
data: {
tasks: [
{ id: 1, name: 'Studying JavaScript' },
{ id: 2, name: 'Studying PHP' },
{ id: 3, name: 'Studying Ruby' },
]
}
})
v-forを使用してループ処理
var vm = new Vue({
el: '#tasks-index',
data: {
tasks: [
{ id: 1, name: 'Studying JavaScript' },
{ id: 2, name: 'Studying PHP' },
{ id: 3, name: 'Studying Ruby' },
]
}
})
HTMLのテーブルタグの方にid="tasks-index"
を割り当てておきます。
また、v-for
を使用してtasks
の値をループさせて出力します。
v-for
+ <table id="tasks-index" class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
+ <tr v-for="task in tasks">
+ <td>{{ task.name }}</td>
<td>
<div class="btn btn-danger">Done!</div>
</td>
</tr>
<tr>
<td><input class="form-control"></td>
<td>
<div class="btn btn-default">Create Task</div>
</td>
</tr>
</tbody>
</table>
これで、一覧表示はできましたので、次は新規登録です!
タスクの新規登録
クリックイベントの設定
「Create Task」ボタンが押されたら、tasks
プロパティに値を追加したいので、クリックイベントを設定します。
v-on:click
を使用すれば、設定したインスタンスメソッドにとばすことができます。
v-on
イベントハンドリング
今回は後ほど、createTask
というメソッドを作りたいと思います。
<tr>
+ <td><input v-model="newTask" class="form-control"></td>
<td>
+ <div class="btn btn-default" v-on:click="createTask">Create Task</div>
</td>
</tr>
</tbody>
</table>
また、入力フォームとしてinput
タグを使用していますが、そこにv-model
でnewTask
というプロパティをバインディングしています。
新規登録に際し、新しい値をどこかに保持する必要があると考えたのですが、とりあえず新しいインスタンスプロパティを用意し、そこに保持する方法としました。
(このあたりはもっとスマートな方法がありそうです。。。)
v-model
インスタンスに追記
var vm = new Vue({
el: '#tasks-index',
data: {
tasks: [
{ id: 1, name: 'Studying JavaScript' },
{ id: 2, name: 'Studying PHP' },
{ id: 3, name: 'Studying Ruby' },
],
+ newTask: '',
},
+ methods: {
+ createTask: function (event) {
+ // 新しいIDを、配列長から取得
+ var new_id = this.tasks.length + 1;
+ // 配列に追加
+ this.tasks.push({ name: this.newTask });
+ // プロパティを空に戻す
+ this.newTask = '';
+ }
+ }
})
タスクの完了(配列から削除)
タスクの完了は、要はtasks
プロパティからの削除とします。
クリックイベントの設定
+ <div class="btn btn-danger" v-on:click="doneTask(task.id)">Done!</div>
メソッドの追記
methods: {
createTask: function () {
var new_id = this.tasks.length + 1;
this.tasks.push({ id: new_id, name: this.newTask });
this.newTask = '';
+ },
+ doneTask: function (task_id) {
+ this.$delete(this.tasks, task_id - 1);
+ }
}
新規登録時のid取得方法を修正
7/7 追記
riawiththesamさんにコメントにてご指摘いただきました。
JSON配列長から新IDを取得してしまうと、物理削除した後にIDの不整合が起こってしまうので、以下のように修正しました。
methods: {
createTask: function () {
- var new_id = this.tasks.length + 1;
+ var new_id = this.tasks[this.tasks.length - 1].id + 1;
this.tasks.push({ id: new_id, name: this.newTask });
this.newTask = '';
},
少しブサイクですが、配列の最後のidの値から計算するようにしました。
(もうちょっと良い書き方がありそうですが。。。)
論理削除に修正
7/9 追記
上記の修正に合わせ、tasks
にisDeleted
をもたせて、タスクの完了を論理削除にしたいと思います。
Vueインスタンスの修正
先にVueインスタンスのcreateTask
メソッドとdoneTask
メソッドを修正していきます。
methods: {
createTask: function () {
var new_id = this.tasks[this.tasks.length - 1].id + 1;
- this.tasks.push({ id: new_id, name: this.newTask });
+ this.tasks.push({ id: new_id, name: this.newTask, isDeleted: false });
this.newTask = '';
},
doneTask: function (task_id) {
- this.$delete(this.tasks, task_id - 1);
+ this.tasks.filter(function (task) {
+ if (task.id === task_id) {
+ return task.isDeleted = true;
+ }
+ })
}
}
doneTask
でJSのfilter
関数を使用します。
これでidが一致した場合にその要素のisDeleted
を書き換えます。
filter
初期値にもisDeleted
を追加しておきます。
data: {
tasks: [
{ id: 1, name: 'Studying JavaScript', isDeleted: false },
{ id: 2, name: 'Studying PHP', isDeleted: false },
{ id: 3, name: 'Studying Ruby', isDeleted: false },
],
}
7/12 追記
私の理解不足でしたが、filter
は新しい配列を作成してしまうので、forEach
を使用した方が良い、というご指摘をいただきました。
そのため、doneTask
メソッドを下記のように修正しました。
doneTask: function (task_id) {
- this.tasks.filter(function (task) {
+ this.tasks.forEach(function (task) {
if (task.id === task_id) {
return task.isDeleted = true;
}
})
}
v-forとv-ifで条件ループ
v-if
v-forとv-if
v-for
とv-if
を合わせて使用することで、条件分岐しつつループレンダリングできます。
今回はisDeleted
がtrueのもののみ表示させます。
<!-- 省略 -->
<tbody>
- <tr v-for="task in tasks">
+ <tr v-for="task in tasks" v-if="!task.isDeleted">
<td>{{ task.name }}</td>
<!-- 省略 -->
さいごに
簡単ではありますが、勉強用に作成してみました。
次の目標はRailsに組み込んで、もう少し手の込んだSPAを作りたいと思います!
もろもろミスがあり、申し訳ありません。
7/10 追記
本記事をブログの方でも公開しました。
よろしければご覧ください。
Vue.js入門その3〜簡単にTODOアプリを作ってみたよ〜
Author And Source
この問題について(Vue.jsの勉強で超簡単なタスク管理アプリを作ってみる), 我々は、より多くの情報をここで見つけました https://qiita.com/naoki85/items/dfdca5786df99dbdbd1a著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .