diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index 9a9a654d4cd..1c4679f2d21 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -375,12 +375,18 @@ function genScopedSlots ( containsSlotChild(slot) // is passing down slot from parent which may be dynamic ) }) - // OR when it is inside another scoped slot (the reactivity is disconnected) - // #9438 + // OR when it is inside another scoped slot or v-for (the reactivity may be + // disconnected due to the intermediate scope variable) + // #9438, #9506 + // TODO: this can be further optimized by properly analyzing in-scope bindings + // and skip force updating ones that do not actually use scope variables. if (!needsForceUpdate) { let parent = el.parent while (parent) { - if (parent.slotScope && parent.slotScope !== emptySlotScopeToken) { + if ( + (parent.slotScope && parent.slotScope !== emptySlotScopeToken) || + parent.for + ) { needsForceUpdate = true break } diff --git a/test/unit/features/component/component-scoped-slot.spec.js b/test/unit/features/component/component-scoped-slot.spec.js index 858f237e9bb..2aadba239b4 100644 --- a/test/unit/features/component/component-scoped-slot.spec.js +++ b/test/unit/features/component/component-scoped-slot.spec.js @@ -1171,4 +1171,30 @@ describe('Component scoped slot', () => { expect(vm.$el.textContent).toBe('bar') }).then(done) }) + + it('should not skip updates for v-slot inside v-for', done => { + const test = { + template: `
` + } + + const vm = new Vue({ + template: ` +
+
+ {{ i }} +
+
+ `, + components: { test }, + data: { + numbers: [1] + } + }).$mount() + + expect(vm.$el.textContent).toBe(`1`) + vm.numbers = [2] + waitForUpdate(() => { + expect(vm.$el.textContent).toBe(`2`) + }).then(done) + }) })