Skip to content

Commit 767e623

Browse files
committed
add back support for non-standard literal keys in track-by
1 parent 47375c5 commit 767e623

File tree

2 files changed

+66
-15
lines changed

2 files changed

+66
-15
lines changed

src/directives/public/for.js

+22-15
Original file line numberDiff line numberDiff line change
@@ -403,11 +403,7 @@ const vFor = {
403403
var primitive = !isObject(value)
404404
var id
405405
if (key || trackByKey || primitive) {
406-
id = trackByKey
407-
? trackByKey === '$index'
408-
? index
409-
: getPath(value, trackByKey)
410-
: (key || value)
406+
id = getTrackByKey(index, key, value, trackByKey)
411407
if (!cache[id]) {
412408
cache[id] = frag
413409
} else if (trackByKey !== '$index') {
@@ -444,11 +440,7 @@ const vFor = {
444440
var primitive = !isObject(value)
445441
var frag
446442
if (key || trackByKey || primitive) {
447-
var id = trackByKey
448-
? trackByKey === '$index'
449-
? index
450-
: getPath(value, trackByKey)
451-
: (key || value)
443+
var id = getTrackByKey(index, key, value, trackByKey)
452444
frag = this.cache[id]
453445
} else {
454446
frag = value[this.id]
@@ -476,11 +468,7 @@ const vFor = {
476468
var key = hasOwn(scope, '$key') && scope.$key
477469
var primitive = !isObject(value)
478470
if (trackByKey || key || primitive) {
479-
var id = trackByKey
480-
? trackByKey === '$index'
481-
? index
482-
: getPath(value, trackByKey)
483-
: (key || value)
471+
var id = getTrackByKey(index, key, value, trackByKey)
484472
this.cache[id] = null
485473
} else {
486474
value[this.id] = null
@@ -635,6 +623,25 @@ function range (n) {
635623
return ret
636624
}
637625

626+
/**
627+
* Get the track by key for an item.
628+
*
629+
* @param {Number} index
630+
* @param {String} key
631+
* @param {*} value
632+
* @param {String} [trackByKey]
633+
*/
634+
635+
function getTrackByKey (index, key, value, trackByKey) {
636+
return trackByKey
637+
? trackByKey === '$index'
638+
? index
639+
: trackByKey.charAt(0).match(/\w/)
640+
? getPath(value, trackByKey)
641+
: value[trackByKey]
642+
: (key || value)
643+
}
644+
638645
if (process.env.NODE_ENV !== 'production') {
639646
vFor.warnDuplicate = function (value) {
640647
warn(

test/unit/specs/directives/public/for/for_spec.js

+44
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,50 @@ describe('v-for', function () {
572572
}
573573
})
574574

575+
it('track by non-standard id path', function (done) {
576+
var vm = new Vue({
577+
el: el,
578+
template: '<test v-for="item in list" :item="item" track-by=".id"></test>',
579+
data: {
580+
list: [
581+
{ '.id': 1, msg: 'foo' },
582+
{ '.id': 2, msg: 'bar' },
583+
{ '.id': 3, msg: 'baz' }
584+
]
585+
},
586+
components: {
587+
test: {
588+
props: ['item'],
589+
template: '{{item.msg}}'
590+
}
591+
}
592+
})
593+
assertMarkup()
594+
var oldVms = vm.$children.slice()
595+
// swap the data with different objects, but with
596+
// the same ID!
597+
vm.list = [
598+
{ '.id': 1, msg: 'qux' },
599+
{ '.id': 2, msg: 'quux' }
600+
]
601+
_.nextTick(function () {
602+
assertMarkup()
603+
// should reuse old vms!
604+
var i = 2
605+
while (i--) {
606+
expect(vm.$children[i]).toBe(oldVms[i])
607+
}
608+
done()
609+
})
610+
611+
function assertMarkup () {
612+
var markup = vm.list.map(function (item) {
613+
return '<test>' + item.msg + '</test>'
614+
}).join('')
615+
expect(el.innerHTML).toBe(markup)
616+
}
617+
})
618+
575619
it('track by $index', function (done) {
576620
var vm = new Vue({
577621
el: el,

0 commit comments

Comments
 (0)