Skip to content

Commit 50e323c

Browse files
committed
support track-by="$index"
1 parent b769891 commit 50e323c

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

src/directives/repeat.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ module.exports = {
249249
for (i = 0, l = data.length; i < l; i++) {
250250
obj = data[i]
251251
raw = converted ? obj.$value : obj
252-
vm = !init && this.getVm(raw, converted ? obj.$key : null)
252+
vm = !init && this.getVm(raw, i, converted ? obj.$key : null)
253253
if (vm) { // reusable instance
254254
vm._reused = true
255255
vm.$index = i // update $index
@@ -375,7 +375,7 @@ module.exports = {
375375
vm._repeat = true
376376
// cache instance
377377
if (needCache) {
378-
this.cacheVm(raw, vm, this.converted ? meta.$key : null)
378+
this.cacheVm(raw, vm, index, this.converted ? meta.$key : null)
379379
}
380380
// sync back changes for two-way bindings of primitive values
381381
var type = typeof raw
@@ -427,15 +427,20 @@ module.exports = {
427427
*
428428
* @param {Object} data
429429
* @param {Vue} vm
430+
* @param {Number} index
430431
* @param {String} [key]
431432
*/
432433

433-
cacheVm: function (data, vm, key) {
434+
cacheVm: function (data, vm, index, key) {
434435
var idKey = this.idKey
435436
var cache = this.cache
436437
var id
437438
if (key || idKey) {
438-
id = idKey ? data[idKey] : key
439+
var id = idKey
440+
? idKey === '$index'
441+
? index
442+
: data[idKey]
443+
: key
439444
if (!cache[id]) {
440445
cache[id] = vm
441446
} else {
@@ -469,14 +474,19 @@ module.exports = {
469474
* Try to get a cached instance from a piece of data.
470475
*
471476
* @param {Object} data
477+
* @param {Number} index
472478
* @param {String} [key]
473479
* @return {Vue|undefined}
474480
*/
475481

476-
getVm: function (data, key) {
482+
getVm: function (data, index, key) {
477483
var idKey = this.idKey
478484
if (key || idKey) {
479-
var id = idKey ? data[idKey] : key
485+
var id = idKey
486+
? idKey === '$index'
487+
? index
488+
: data[idKey]
489+
: key
480490
return this.cache[id]
481491
} else if (isObject(data)) {
482492
return data[this.id]
@@ -507,7 +517,11 @@ module.exports = {
507517
var idKey = this.idKey
508518
var convertedKey = vm.$key
509519
if (idKey || convertedKey) {
510-
var id = idKey ? data[idKey] : convertedKey
520+
var id = idKey
521+
? idKey === '$index'
522+
? vm.$index
523+
: data[idKey]
524+
: convertedKey
511525
this.cache[id] = null
512526
} else if (isObject(data)) {
513527
data[this.id] = null

test/unit/specs/directives/repeat_spec.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,34 @@ if (_.inBrowser) {
496496
}
497497
})
498498

499+
it('track by $index', function (done) {
500+
var vm = new Vue({
501+
el: el,
502+
data: {
503+
items: [{a:1}, {a:2}]
504+
},
505+
template: '<div v-repeat="items" track-by="$index">{{$index}} {{a}}</div>'
506+
})
507+
508+
assertMarkup()
509+
var el1 = el.children[0]
510+
var el2 = el.children[1]
511+
vm.items = [{a:3}, {a:2}, {a:1}]
512+
_.nextTick(function () {
513+
assertMarkup()
514+
// should mutate the DOM in-place
515+
expect(el.children[0]).toBe(el1)
516+
expect(el.children[1]).toBe(el2)
517+
done()
518+
})
519+
520+
function assertMarkup () {
521+
expect(el.innerHTML).toBe(vm.items.map(function (item, i) {
522+
return '<div>' + i + ' ' + item.a + '</div>'
523+
}).join(''))
524+
}
525+
})
526+
499527
it('warn duplicate objects', function () {
500528
var obj = {}
501529
var vm = new Vue({

0 commit comments

Comments
 (0)