LoginSignup
3
3

More than 5 years have passed since last update.

[Vue.js] v-repeatした配列にフィルタを掛けた時の$indexに注意

Last updated at Posted at 2015-09-17

v-repeatにorderByでフィルタをしたときの$indexを使って、rootのdataを更新しようとすると、意図しないオブジェクトが取得される。ということにハマったのでメモ。

やること

  • contents配列の各オブジェクトをv-repeat
  • orderByを使って、dateTimeの降順で表示
index.html
<div id="list">
  <ul>
    <li v-repeat="content in contents | orderBy 'dateTime' true">
      index: {{$index}} - id: {{content.id}} - {{content.memo}} - {{content.dateTime}}
      <button v-on="click : outputIndex(this)">button</button>
    </li>
  </ul>
</div>
index.js
var List = new Vue({
  el: '#list',
  data: {
    contents: [
      {id: 1, memo: 'memo 1', dateTime: '2015/9/10'},
      {id: 2, memo: 'memo 2', dateTime: '2015/9/11'},
      {id: 3, memo: 'memo 3', dateTime: '2015/9/12'},
      {id: 4, memo: 'memo 4', dateTime: '2015/9/13'},
      {id: 5, memo: 'memo 5', dateTime: '2015/9/14'},
      {id: 6, memo: 'memo 6', dateTime: '2015/9/15'}
    ]
  },
  methods: {
    outputIndex: function (item) {
      // targetVMの$index
      console.log('index: ' + item.$index);
      // targetVMのid
      console.log('id (targetVM): ' + item.content.id);
      // targetVMの$indexでイベントが起きた1件のオブジェクトを検索
      console.log('id (this.contents): ' + this.contents[item.$index].id)

    }
})

Kobito.m9S3RS.png

buttonをclick

Kobito.68v8Ro.png

targetVMはid: 1のオブジェクトだが、その$indexをrootで利用すると意図しないオブジェクトが取得される。 orderByで子インスタンスがソートされるとき、contents内の配列がソートされるわけではないので$indexで取れる値と一致しなくなるのが原因。

起きた問題

$set()等のデータを更新するメソッドで意図しないオブジェクトのデータが更新される。indexに依存した処理が正しく機能しなくなった。

解決策

ユニークなidでcontentsを検索して正しいindexを取得する

var list = new Vue({
  el: '#list',
  data: {
    contents: [
      {id: 1, memo: 'memo 1', dateTime: '2015/9/10'},
      {id: 2, memo: 'memo 2', dateTime: '2015/9/11'},
      {id: 3, memo: 'memo 3', dateTime: '2015/9/12'},
      {id: 4, memo: 'memo 4', dateTime: '2015/9/13'},
      {id: 5, memo: 'memo 5', dateTime: '2015/9/14'},
      {id: 6, memo: 'memo 6', dateTime: '2015/9/15'},
    ]
  },
  methods: {

    outputIdx: function (item) {
      var id = item.content.id;
      var idx = this.findById(id)

      console.log('index: ' + item.$index);
      console.log('id (targetVM): ' + item.content.id);
      console.log('id (this.contents): ' + this.contents[item.$index].id)

      console.log('正しいindex: ' + idx);
      console.log('targetVMのid:' + id);
    },

    // idを渡して正しいindexを取得するメソッド
    findById: function (id) {
      for (var i = 0; i < this.contents.length; i++ ) {
        if (this.contents[i].id === id) {
          return i
        }
      }
    }
  }
})

Kobito.lkuL63.png

独学手探りプログラミングおじさんが出した解決策です。
もっとよい解決策があればご指摘よろしくお願いします。

3
3
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
3
3