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 vuejs#7710
  • Loading branch information
yyx990803 authored and hefeng committed Jan 25, 2019
1 parent b301e5f commit 36d20d1
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 36d20d1

Please sign in to comment.