diff --git a/src/core/vdom/create-functional-component.js b/src/core/vdom/create-functional-component.js index 78a73def132..655de0deee3 100644 --- a/src/core/vdom/create-functional-component.js +++ b/src/core/vdom/create-functional-component.js @@ -48,10 +48,16 @@ export function FunctionalRenderContext ( this.children = children this.parent = parent this.listeners = data.on || emptyObject - this.scopedSlots = data.scopedSlots || emptyObject this.injections = resolveInject(options.inject, parent) this.slots = () => resolveSlots(children, parent) + Object.defineProperty(this, 'scopedSlots', { + enumerable: true, + get () { + return normalizeScopedSlots(data.scopedSlots, this.slots()) + } + }) + // support for compiled functional template if (isCompiled) { // exposing $options for renderStatic() diff --git a/src/core/vdom/helpers/normalize-scoped-slots.js b/src/core/vdom/helpers/normalize-scoped-slots.js index 3672d7e7758..12454ebfad5 100644 --- a/src/core/vdom/helpers/normalize-scoped-slots.js +++ b/src/core/vdom/helpers/normalize-scoped-slots.js @@ -21,6 +21,7 @@ export function normalizeScopedSlots ( } res._normalized = true } + // expose normal slots on scopedSlots if (normalSlots !== emptyObject) { for (const key in normalSlots) { res[key] = () => normalSlots[key] diff --git a/test/unit/features/options/functional.spec.js b/test/unit/features/options/functional.spec.js index a4ae7ce4377..ea85eea8a7f 100644 --- a/test/unit/features/options/functional.spec.js +++ b/test/unit/features/options/functional.spec.js @@ -79,21 +79,25 @@ describe('Options functional', () => { document.body.removeChild(vm.$el) }) - it('should expose data.scopedSlots as scopedSlots', () => { + it('should expose scopedSlots on render context', () => { const vm = new Vue({ - template: '

{{ a }}

', + template: '
foo

{{ a }}

', components: { wrap: { functional: true, - render (h, { scopedSlots, data }) { - expect(data.scopedSlots).toBe(scopedSlots) - return data.scopedSlots.default('a') + render (h, { scopedSlots }) { + return [ + // scoped + scopedSlots.p('a'), + // normal slot content should be exposed as well + scopedSlots.default() + ] } } } }).$mount() - expect(vm.$el.textContent).toBe('a') + expect(vm.$el.textContent).toBe('afoo') }) it('should support returning more than one root node', () => {