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 12, 2018
1 parent 1049461 commit 9919a96
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 9919a96

Please sign in to comment.