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)
}
})
buttonをclick
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
}
}
}
}
})
独学手探りプログラミングおじさんが出した解決策です。
もっとよい解決策があればご指摘よろしくお願いします。