diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index acb3ca9118c..ddb58c16a6d 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -430,7 +430,14 @@ function containsSlotChild (el: ASTNode): boolean { if (el.tag === 'slot') { return true } - return el.children.some(containsSlotChild) + // #12232, #12245: nested scoped slot should update + const childrenIsDynamic = el.children.some(containsSlotChild) + if (childrenIsDynamic) { + return childrenIsDynamic + } else if (el.scopedSlots) { + const scopedSlots = el.scopedSlots + return Object.keys(scopedSlots).some(key => containsSlotChild(scopedSlots[key])) + } } return false } diff --git a/test/unit/features/component/component-scoped-slot.spec.js b/test/unit/features/component/component-scoped-slot.spec.js index a77b055ccd6..118fdbe0a09 100644 --- a/test/unit/features/component/component-scoped-slot.spec.js +++ b/test/unit/features/component/component-scoped-slot.spec.js @@ -1026,6 +1026,72 @@ describe('Component scoped slot', () => { }).then(done) }) + // #12232, #12245 + it('nested named scoped slots should update', done => { + const initialText = 'initial' + const scopedSlotContent = 'scopedSlot' + + const inner = { + template: `
` + } + + const innerContainer = { + template: `
` + } + + const wrapper = { + components: { inner, innerContainer }, + name: 'wrapper', + template: ` + + + + + + ` + } + + const outer = { + components: { wrapper }, + template: ` + +
+ {{ text }} + +
+
+ `, + data() { + return { + text: initialText, + } + }, + } + + const vm = new Vue({ + components: { outer }, + template: `` + }).$mount() + + expect(vm.$el.textContent).toBe(`${scopedSlotContent} ${initialText} `) + + const newValue = 'newValue' + vm.$refs.outer.text = newValue + const input = vm.$el.querySelector('input') + input.value = newValue + triggerEvent(input, 'input') + + waitForUpdate(() => { + expect(vm.$el.textContent).toBe(`${scopedSlotContent} ${newValue} `) + expect(input.value).toBe(newValue) + }).then(done) + }) + it('dynamic v-bind arguments on ', done => { const Foo = { data() {