From 21fca2fffc3a75235a6656eb85ae40835e04bf69 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 11 Feb 2019 11:30:14 -0500 Subject: [PATCH] fix: ensure scoped slot containing passed down slot content updates properly --- src/compiler/codegen/index.js | 17 ++++++++++- .../component/component-scoped-slot.spec.js | 29 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index 93ae4cbc21f..9a9a654d4cd 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -368,7 +368,12 @@ function genScopedSlots ( // for example if the slot contains dynamic names, has v-if or v-for on them... let needsForceUpdate = Object.keys(slots).some(key => { const slot = slots[key] - return slot.slotTargetDynamic || slot.if || slot.for + return ( + slot.slotTargetDynamic || + slot.if || + slot.for || + 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 @@ -390,6 +395,16 @@ function genScopedSlots ( }]${needsForceUpdate ? `,true` : ``})` } +function containsSlotChild (el: ASTNode): boolean { + if (el.type === 1) { + if (el.tag === 'slot') { + return true + } + return el.children.some(containsSlotChild) + } + return false +} + function genScopedSlot ( el: ASTElement, state: CodegenState diff --git a/test/unit/features/component/component-scoped-slot.spec.js b/test/unit/features/component/component-scoped-slot.spec.js index 30e51b9393b..858f237e9bb 100644 --- a/test/unit/features/component/component-scoped-slot.spec.js +++ b/test/unit/features/component/component-scoped-slot.spec.js @@ -1104,7 +1104,7 @@ describe('Component scoped slot', () => { expect(vm.$el.textContent).toBe('hello') }) - it('should not cache scoped slot normalzation when there are a mix of normal and scoped slots', done => { + it('should not cache scoped slot normalization when there are a mix of normal and scoped slots', done => { const foo = { template: `
` } @@ -1144,4 +1144,31 @@ describe('Component scoped slot', () => { expect(vm.$el.textContent).toBe('foo bar') }) + + it('should not skip updates when a scoped slot contains parent content', done => { + const inner = { + template: `
` + } + + const wrapper = { + template: ``, + components: { inner } + } + + const vm = new Vue({ + data() { + return { + ok: true + } + }, + components: { wrapper }, + template: `
{{ ok ? 'foo' : 'bar' }}
` + }).$mount() + + expect(vm.$el.textContent).toBe('foo') + vm.ok = false + waitForUpdate(() => { + expect(vm.$el.textContent).toBe('bar') + }).then(done) + }) })