diff --git a/src/core/vdom/create-functional-component.js b/src/core/vdom/create-functional-component.js index efed801db7d..d9f4d6fba69 100644 --- a/src/core/vdom/create-functional-component.js +++ b/src/core/vdom/create-functional-component.js @@ -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, @@ -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 diff --git a/test/unit/features/options/functional.spec.js b/test/unit/features/options/functional.spec.js index 2c6abe95972..972e7a3401f 100644 --- a/test/unit/features/options/functional.spec.js +++ b/test/unit/features/options/functional.spec.js @@ -242,6 +242,34 @@ describe('Options functional', () => { expect(vm.$el.childNodes[1].namespaceURI).toContain('svg') }) + it('should accept components', () => { + const HelloComp = { + template: `
Hello
` + } + + const WorldComp = { + template: `
World
` + } + + const Child = { + functional: true, + components: { + HelloComp + }, + render: h => [h('hello-comp'), h('world-comp')] + } + + const vm = new Vue({ + template: `
`, + components: { + Child, + WorldComp + } + }).$mount() + + expect(vm.$el.innerHTML).toBe('
Hello
World
') + }) + it('should work with render fns compiled from template', done => { // code generated via vue-template-es2015-compiler var render = function (_h, _vm) { diff --git a/types/options.d.ts b/types/options.d.ts index cc58affe6a1..6710a0bf247 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -113,6 +113,7 @@ export interface FunctionalComponentOptions | AsyncComponent }; render?(this: undefined, createElement: CreateElement, context: RenderContext): VNode; }