fix: named slots for nested functional components

Named slots should be respecred when passing raw children down multiple
layers of functional components.

fix #7710
This commit is contained in:
Evan You 2018-03-12 15:39:39 -04:00
parent 215f877d1b
commit 6dd73e9ee4
2 changed files with 47 additions and 6 deletions

View File

@ -10,6 +10,7 @@ import { installRenderHelpers } from '../instance/render-helpers/index'
import {
isDef,
isTrue,
hasOwn,
camelize,
emptyObject,
validateProp
@ -23,6 +24,21 @@ export function FunctionalRenderContext (
Ctor: Class<Component>
) {
const options = Ctor.options
// ensure the createElement function in functional components
// gets a unique context - this is necessary for correct named slot check
let contextVm
if (hasOwn(parent, '_uid')) {
contextVm = Object.create(parent)
// $flow-disable-line
contextVm._original = parent
} else {
contextVm = parent
// $flow-disable-line
parent = parent._original
}
const isCompiled = isTrue(options._compiled)
const needNormalization = !isCompiled
this.data = data
this.props = props
this.children = children
@ -31,12 +47,6 @@ export function FunctionalRenderContext (
this.injections = resolveInject(options.inject, parent)
this.slots = () => resolveSlots(children, parent)
// ensure the createElement function in functional components
// gets a unique context - this is necessary for correct named slot check
const contextVm = Object.create(parent)
const isCompiled = isTrue(options._compiled)
const needNormalization = !isCompiled
// support for compiled functional template
if (isCompiled) {
// exposing $options for renderStatic()

View File

@ -824,4 +824,35 @@ describe('Component slot', () => {
expect(vm.$el.textContent).toBe('hello')
}).then(done)
})
it('should allow passing named slots as raw children down multiple layers of functional component', () => {
const CompB = {
functional: true,
render (h, { slots }) {
return slots().foo
}
}
const CompA = {
functional: true,
render (h, { children }) {
return h(CompB, children)
}
}
const vm = new Vue({
components: {
CompA
},
template: `
<div>
<comp-a>
<span slot="foo">foo</span>
</comp-a>
</div>
`
}).$mount()
expect(vm.$el.textContent).toBe('foo')
})
})