2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vue.jsのv-forでの並び順を逆順にした際の現象と注意点と対策

Last updated at Posted at 2020-01-05

はじめに

現在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初学者の参考になればいいと思います。

2
1
1

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?