From ca7f05793cae8899b5329df77e3139002e2c72d8 Mon Sep 17 00:00:00 2001 From: Alexander Lichter Date: Mon, 18 Jun 2018 10:42:40 +0200 Subject: [PATCH] fix(slots): functional component text slots --- flow/options.flow.js | 2 +- packages/create-instance/add-slots.js | 17 +++++---- .../create-functional-component.js | 35 ++----------------- test/specs/mounting-options/slots.spec.js | 19 ++++++++++ 4 files changed, 33 insertions(+), 40 deletions(-) diff --git a/flow/options.flow.js b/flow/options.flow.js index 618e47eed..9765cd612 100644 --- a/flow/options.flow.js +++ b/flow/options.flow.js @@ -4,7 +4,7 @@ declare type Options = { propsData?: Object, mocks?: Object, methods?: Object, - slots?: Object, + slots?: SlotsObject, scopedSlots?: Object, localVue?: Component, provide?: Object, diff --git a/packages/create-instance/add-slots.js b/packages/create-instance/add-slots.js index 746cae35b..8c360d59e 100644 --- a/packages/create-instance/add-slots.js +++ b/packages/create-instance/add-slots.js @@ -6,7 +6,7 @@ function startsWithTag (str) { return str && str.trim()[0] === '<' } -function createVNodesForSlot ( +export function createVNodesForSlot ( h: Function, slotValue: SlotValue, name: string @@ -30,12 +30,17 @@ export function createSlotVNodes ( return Object.keys(slots).reduce((acc, key) => { const content = slots[key] if (Array.isArray(content)) { - const nodes = content.reduce((accInner, slotDef) => { - return accInner.concat(createVNodesForSlot(h, slotDef, key)) - }, []) + const nodes = content.map(slotDef => createVNodesForSlot(h, slotDef, key)) return acc.concat(nodes) - } else { - return acc.concat(createVNodesForSlot(h, content, key)) } + + return acc.concat(createVNodesForSlot(h, content, key)) }, []) } + +export function createFunctionalSlotVNodes ( + h: Function, + slots: ?SlotsObject +) { + return createSlotVNodes(h, slots || {}) +} diff --git a/packages/create-instance/create-functional-component.js b/packages/create-instance/create-functional-component.js index ab83710c4..f367e6f57 100644 --- a/packages/create-instance/create-functional-component.js +++ b/packages/create-instance/create-functional-component.js @@ -1,39 +1,8 @@ // @flow -import { compileToFunctions } from 'vue-template-compiler' import { throwError } from 'shared/util' import { validateSlots } from './validate-slots' - -function createFunctionalSlots (slots = {}, h) { - if (Array.isArray(slots.default)) { - return slots.default.map(h) - } - - if (typeof slots.default === 'string') { - return [h(compileToFunctions(slots.default))] - } - const children = [] - Object.keys(slots).forEach(slotType => { - if (Array.isArray(slots[slotType])) { - slots[slotType].forEach(slot => { - const component = - typeof slot === 'string' ? compileToFunctions(slot) : slot - const newSlot = h(component) - newSlot.data.slot = slotType - children.push(newSlot) - }) - } else { - const component = - typeof slots[slotType] === 'string' - ? compileToFunctions(slots[slotType]) - : slots[slotType] - const slot = h(component) - slot.data.slot = slotType - children.push(slot) - } - }) - return children -} +import { createFunctionalSlotVNodes } from './add-slots' export default function createFunctionalComponent ( component: Component, @@ -56,7 +25,7 @@ export default function createFunctionalComponent ( mountingOptions.context.children.map( x => (typeof x === 'function' ? x(h) : x) )) || - createFunctionalSlots(mountingOptions.slots, h) + createFunctionalSlotVNodes(h, mountingOptions.slots) ) }, name: component.name, diff --git a/test/specs/mounting-options/slots.spec.js b/test/specs/mounting-options/slots.spec.js index 8d56654a3..d0e769312 100644 --- a/test/specs/mounting-options/slots.spec.js +++ b/test/specs/mounting-options/slots.spec.js @@ -235,6 +235,25 @@ describeWithMountingMethods('options.slots', mountingMethod => { } }) + it('mounts functional component with text slot', () => { + const TestComponent = { + name: 'component-with-slots', + functional: true, + render: (h, ctx) => h('div', ctx.data, [ctx.slots().default, ctx.slots().header]) + } + const wrapper = mountingMethod(TestComponent, { + slots: { + default: 'hello,', + header: 'world' + } + }) + if (mountingMethod.name === 'renderToString') { + expect(wrapper).contains('hello,world') + } else { + expect(wrapper.text()).to.contain('hello,world') + } + }) + it('mounts component with named slot if passed component in slot object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: {