Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/core/vdom/create-functional-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { resolveInject } from '../instance/inject'
import { normalizeChildren } from '../vdom/helpers/normalize-children'
import { resolveSlots } from '../instance/render-helpers/resolve-slots'
import { installRenderHelpers } from '../instance/render-helpers/index'
import { extend } from 'shared/util'

import {
isDef,
Expand All @@ -26,19 +27,23 @@ export function FunctionalRenderContext (
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
const contextVm = Object.create(parent)
if (hasOwn(parent, '_uid')) {
contextVm = Object.create(parent)
// $flow-disable-line
contextVm._original = parent
} else {
// the context vm passed in is a functional context as well.
// in this case we want to make sure we are able to get a hold to the
// real context instance.
contextVm = parent

// $flow-disable-line
parent = parent._original
}

// support functional components hash
contextVm.$options = Object.create(contextVm.$options)
contextVm.$options.components = extend(Object.create(contextVm.$options.components || {}), options.components)

const isCompiled = isTrue(options._compiled)
const needNormalization = !isCompiled

Expand Down
28 changes: 28 additions & 0 deletions test/unit/features/options/functional.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,34 @@ describe('Options functional', () => {
expect(vm.$el.childNodes[1].namespaceURI).toContain('svg')
})

it('should accept components', () => {
const HelloComp = {
template: `<div>Hello</div>`
}

const WorldComp = {
template: `<div>World</div>`
}

const Child = {
functional: true,
components: {
HelloComp
},
render: h => [h('hello-comp'), h('world-comp')]
}

const vm = new Vue({
template: `<div><child/></div>`,
components: {
Child,
WorldComp
}
}).$mount()

expect(vm.$el.innerHTML).toBe('<div>Hello</div><div>World</div>')
})

it('should work with render fns compiled from template', done => {
// code generated via vue-template-es2015-compiler
var render = function (_h, _vm) {
Expand Down
1 change: 1 addition & 0 deletions types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export interface FunctionalComponentOptions<Props = DefaultProps, PropDefs = Pro
props?: PropDefs;
inject?: InjectOptions;
functional: boolean;
components?: { [key: string]: Component<any, any, any, any> | AsyncComponent<any, any, any, any> };
render?(this: undefined, createElement: CreateElement, context: RenderContext<Props>): VNode;
}

Expand Down