Skip to content
Permalink
Browse files

fix: named slots for nested functional components

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 215f877 commit 6dd73e9ee44c09f04d3f616fcce18750a55e2e4f
Showing with 47 additions and 6 deletions.
  1. +16 −6 src/core/vdom/create-functional-component.js
  2. +31 −0 test/unit/features/component/component-slot.spec.js
@@ -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()
@@ -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.
You can’t perform that action at this time.