Skip to content

Commit

Permalink
fix: named slots for nested functional components
Browse files Browse the repository at this point in the history
Named slots should be respecred when passing raw children down multiple
layers of functional components.

fix #7710
  • Loading branch information
yyx990803 committed Mar 13, 2018
1 parent 215f877 commit 6dd73e9
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
22 changes: 16 additions & 6 deletions src/core/vdom/create-functional-component.js
Expand Up @@ -10,6 +10,7 @@ import { installRenderHelpers } from '../instance/render-helpers/index'
import {
isDef,
isTrue,
hasOwn,
camelize,
emptyObject,
validateProp
Expand All @@ -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
Expand All @@ -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()
Expand Down
31 changes: 31 additions & 0 deletions test/unit/features/component/component-slot.spec.js
Expand Up @@ -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')
})
})

0 comments on commit 6dd73e9

Please sign in to comment.