Skip to content

Commit 2e40791

Browse files
committed
fix #929 block repeat with component diffing
1 parent 1c18875 commit 2e40791

File tree

3 files changed

+65
-8
lines changed

3 files changed

+65
-8
lines changed

src/directives/repeat.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module.exports = {
2424
this.id = '__v_repeat_' + (++uid)
2525
// setup anchor nodes
2626
this.start = _.createAnchor('v-repeat-start')
27-
this.end = _.createAnchor('v-repeat')
27+
this.end = _.createAnchor('v-repeat-end')
2828
_.replace(this.el, this.end)
2929
_.before(this.start, this.end)
3030
// check if this is a block repeat
@@ -304,7 +304,7 @@ module.exports = {
304304
: targetPrev._blockEnd || targetPrev.$el
305305
: start
306306
if (vm._reused && !vm._staggerCb) {
307-
currentPrev = findPrevVm(vm, start)
307+
currentPrev = findPrevVm(vm, start, this.id)
308308
if (currentPrev !== targetPrev) {
309309
this.move(vm, prevEl)
310310
}
@@ -363,6 +363,8 @@ module.exports = {
363363
_host: this._host,
364364
// pre-compiled linker for simple repeats
365365
_linkFn: this._linkFn,
366+
// identifier, shows that this vm belongs to this collection
367+
_repeatId: this.id
366368
}, Ctor)
367369
// cache instance
368370
if (needCache) {
@@ -668,14 +670,20 @@ module.exports = {
668670
* leaving transition finishes, but its __vue__ reference
669671
* should have been removed so we can skip them.
670672
*
673+
* If this is a block repeat, we want to make sure we only
674+
* return vm that is bound to this v-repeat. (see #929)
675+
*
671676
* @param {Vue} vm
672677
* @param {Comment|Text} anchor
673678
* @return {Vue}
674679
*/
675680

676-
function findPrevVm (vm, anchor) {
681+
function findPrevVm (vm, anchor, id) {
677682
var el = vm.$el.previousSibling
678-
while (!el.__vue__ && el !== anchor) {
683+
while (
684+
(!el.__vue__ || el.__vue__.$options._repeatId !== id) &&
685+
el !== anchor
686+
) {
679687
el = el.previousSibling
680688
}
681689
return el.__vue__
@@ -711,4 +719,4 @@ function toRefObject (vms) {
711719
ref[vms[i].$key] = vms[i]
712720
}
713721
return ref
714-
}
722+
}

src/util/misc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,4 @@ exports.createAnchor = function (content, persist) {
5454
return config.debug
5555
? document.createComment(content)
5656
: document.createTextNode(persist ? ' ' : '')
57-
}
57+
}

test/unit/specs/directives/repeat_spec.js

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,15 @@ if (_.inBrowser) {
311311
vm.list.reverse()
312312
_.nextTick(function () {
313313
assertMarkup()
314-
done()
314+
vm.list.splice(1, 1)
315+
_.nextTick(function () {
316+
assertMarkup()
317+
vm.list.splice(1, 0, { a: 2 })
318+
_.nextTick(function () {
319+
assertMarkup()
320+
done()
321+
})
322+
})
315323
})
316324

317325
function assertMarkup () {
@@ -322,6 +330,47 @@ if (_.inBrowser) {
322330
}
323331
})
324332

333+
it('block repeat with component', function (done) {
334+
var vm = new Vue({
335+
el: el,
336+
template: '<template v-repeat="list"><test a="{{a}}"></test></template>',
337+
data: {
338+
list: [
339+
{ a: 1 },
340+
{ a: 2 },
341+
{ a: 3 }
342+
]
343+
},
344+
components: {
345+
test: {
346+
props: ['a'],
347+
template: '{{a}}'
348+
}
349+
}
350+
})
351+
assertMarkup()
352+
vm.list.reverse()
353+
_.nextTick(function () {
354+
assertMarkup()
355+
vm.list.splice(1, 1)
356+
_.nextTick(function () {
357+
assertMarkup()
358+
vm.list.splice(1, 0, { a: 2 })
359+
_.nextTick(function () {
360+
assertMarkup()
361+
done()
362+
})
363+
})
364+
})
365+
366+
function assertMarkup () {
367+
var markup = vm.list.map(function (item) {
368+
return '<test>' + item.a + '</test>'
369+
}).join('')
370+
expect(el.innerHTML).toBe(markup)
371+
}
372+
})
373+
325374
it('array filters', function (done) {
326375
var vm = new Vue({
327376
el: el,
@@ -957,4 +1006,4 @@ function assertObjectPrimitiveMutations (vm, el, done) {
9571006
}).join('')
9581007
expect(el.innerHTML).toBe(markup)
9591008
}
960-
}
1009+
}

0 commit comments

Comments
 (0)