はじめに
現在vue.jsにてtodoアプリを作成しており、v-forの順序を逆順にした際に起きた現象と注意点と対策を備忘録としてあげたいと思います。
htmlの部分
App.vue
computed: {
// todoを逆順にしておく
reversTodos() {
return this.todos.slice().reverse();
}
}
App.vue
<transition-group name="slide" tag="ul" class="todo-list">
<li v-for="(todo, index) in reversTodos" :key="todo.id">
<p class="data">Posted date:{{todo.today}}</p>
<p class="deadline" :class="{hurry: todo.isDone}">dead-line:{{todo.deadline}}</p>
<div class="change-btns">
<span class="edit" @click="editForm(index)">edit</span>
<span class="delete" @click="deleteItem(index)">delete</span>
</div>
<p class="title">
<label class="text">
<input type="checkbox" class="check" v-model="todo.isDone" />
<span :class="{done: todo.isDone}">{{todo.title}}</span>
</label>
</p>
<p class="content">{{todo.content}}</p>
</li>
</transition-group>
その後に削除処理を実施。
App.vue
methods: {
// todoの削除
deleteItem(index) {
confirm("delete ok?") ? this.todos.splice(index, 1) : true;
}
}
上記のように表示をさせて削除処理を進めていると問題が起きました。
リストの要素を削除すると別の要素が削除されてしまいました。
落ち着いて考えると分かるのですがcomputedで定義したreversTodosとdataのtodosとで順番が異なってしまったことが原因です。
解決案①
App.vue
<transition-group name="slide" tag="ul" class="todo-list">
//indexの引数を使わない
<li v-for="todo in reversTodos" :key="todo.id">
<p class="data">Posted date:{{todo.today}}</p>
<p class="deadline" :class="{hurry: todo.isDone}">dead-line:{{todo.deadline}}</p>
<div class="change-btns">
//indexでなくtodoを引数に入れる
<span class="edit" @click="editForm(todo)">edit</span>
<span class="delete" @click="deleteItem(todo)">delete</span>
</div>
<p class="title">
<label class="text">
<input type="checkbox" class="check" v-model="todo.isDone" />
<span :class="{done: todo.isDone}">{{todo.title}}</span>
</label>
</p>
<p class="content">{{todo.content}}</p>
</li>
</transition-group>
App.vue
methods: {
// todoの削除
deleteItem(todo) {
var index = this.todos.indexOf(todo)
confirm("delete ok?") ? this.todos.splice(index, 1) : true;
}
}
あくまでもtodosの配列の順番をindexに入れるようにし、削除するようにしました。
解決案②
todoを作成する段階でpush()でなくunshift()を使う。
App.vue
addItem() {
if (this.newTitle == "" || this.newContent == "" || this.selected == "") {
window.alert("Some items have not been entered.");
return false;
}
var today = "";
var item = {
id: this.todos.length,
today: this.calcDay(today),
title: this.newTitle,
content: this.newContent,
selected: this.selected,
deadline: this.calcDay(this.selected),
isDone: false,
}
//unshift()に変更しました。
this.todos.unshift(item);
this.newTitle = this.newContent = this.selected = "";
},
ただ逆にするだけであればこちらの方がシンプルに出来ますね。computedで値を定義する必要もなくなりましたし、他の編集機能を実施する際にもわざわざindexをとる必要もありません。
最後に
まだ僕も学習を始めたばかりでよくわかっていないかもですが、同じくvue.js初学者の参考になればいいと思います。