From 9bcb99d5a3c2fa90b5e9b6ab9c0f2c98c81dd273 Mon Sep 17 00:00:00 2001 From: 38elements Date: Mon, 9 Jul 2018 02:19:06 +0900 Subject: [PATCH 1/9] fix: improve slots option --- .../create-functional-component.js | 2 +- packages/create-instance/create-instance.js | 2 +- .../{add-slots.js => create-slot-vnodes.js} | 13 +++++++- .../components/component-with-parent-name.vue | 17 +++++++++++ test/specs/mounting-options/slots.spec.js | 30 +++++++++++++++++++ 5 files changed, 61 insertions(+), 3 deletions(-) rename packages/create-instance/{add-slots.js => create-slot-vnodes.js} (76%) create mode 100644 test/resources/components/component-with-parent-name.vue diff --git a/packages/create-instance/create-functional-component.js b/packages/create-instance/create-functional-component.js index ee3feb392..04021ba23 100644 --- a/packages/create-instance/create-functional-component.js +++ b/packages/create-instance/create-functional-component.js @@ -2,7 +2,7 @@ import { throwError } from 'shared/util' import { validateSlots } from './validate-slots' -import { createSlotVNodes } from './add-slots' +import { createSlotVNodes } from './create-slot-vnodes' export default function createFunctionalComponent ( component: Component, diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 515ddeff9..29153660b 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -1,6 +1,6 @@ // @flow -import { createSlotVNodes } from './add-slots' +import { createSlotVNodes } from './create-slot-vnodes' import addMocks from './add-mocks' import { addEventLogger } from './log-events' import { createComponentStubs } from 'shared/stub-components' diff --git a/packages/create-instance/add-slots.js b/packages/create-instance/create-slot-vnodes.js similarity index 76% rename from packages/create-instance/add-slots.js rename to packages/create-instance/create-slot-vnodes.js index 86f430f82..f3c48aea0 100644 --- a/packages/create-instance/add-slots.js +++ b/packages/create-instance/create-slot-vnodes.js @@ -1,5 +1,6 @@ // @flow +import Vue from 'vue' import { compileToFunctions } from 'vue-template-compiler' function startsWithTag (str: SlotValue): boolean { @@ -18,7 +19,17 @@ function createVNodesForSlot ( const el = typeof slotValue === 'string' ? compileToFunctions(slotValue) : slotValue - const vnode = h(el) + let vnode = h(el) + if (typeof slotValue === 'string') { + const vue = new Vue() + try { + // $FlowIgnore + vnode = el.render.call(vue._renderProxy, h) + vnode = h(vnode.tag, vnode.data || {}, vnode.children) + } catch (e) { + } + } + vnode.data.slot = name return vnode } diff --git a/test/resources/components/component-with-parent-name.vue b/test/resources/components/component-with-parent-name.vue new file mode 100644 index 000000000..e39fd8cc4 --- /dev/null +++ b/test/resources/components/component-with-parent-name.vue @@ -0,0 +1,17 @@ + + + diff --git a/test/specs/mounting-options/slots.spec.js b/test/specs/mounting-options/slots.spec.js index 19e338b05..d169b971f 100644 --- a/test/specs/mounting-options/slots.spec.js +++ b/test/specs/mounting-options/slots.spec.js @@ -2,8 +2,10 @@ import { compileToFunctions } from 'vue-template-compiler' import Component from '~resources/components/component.vue' import ComponentWithSlots from '~resources/components/component-with-slots.vue' import ComponentAsAClass from '~resources/components/component-as-a-class.vue' +import ComponentWithParentName from '~resources/components/component-with-parent-name.vue' import { describeWithMountingMethods, vueVersion } from '~resources/utils' import { itSkipIf, itDoNotRunIf } from 'conditional-specs' +import { mount } from '~vue/test-utils' describeWithMountingMethods('options.slots', mountingMethod => { it('mounts component with default slot if passed component in slot object', () => { @@ -568,4 +570,32 @@ describeWithMountingMethods('options.slots', mountingMethod => { expect(wrapper.contains(ComponentAsAClass)).to.equal(true) } }) + + itDoNotRunIf( + mountingMethod.name === 'renderToString', + 'sets a component which can access the parent component', + () => { + const wrapperComponent = mount( + { + name: 'parentComponent', + template: '
', + data () { + return { + childName: '' + } + } + }, + { + components: { + ComponentWithParentName + }, + slots: { + default: '' + } + } + ) + expect(wrapperComponent.vm.childName).to.equal('component-with-parent-name') + expect(wrapperComponent.html()).to.equal('
quux
') + } + ) }) From bb24a36ed7f502f169513f282b2842328361a61b Mon Sep 17 00:00:00 2001 From: 38elements Date: Wed, 11 Jul 2018 00:10:40 +0900 Subject: [PATCH 2/9] add test for localVue --- .../create-functional-component.js | 5 +++-- packages/create-instance/create-instance.js | 4 ++-- packages/create-instance/create-slot-vnodes.js | 18 ++++++++++++++---- test/specs/mounting-options/slots.spec.js | 11 +++++++---- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/packages/create-instance/create-functional-component.js b/packages/create-instance/create-functional-component.js index 04021ba23..38e074b16 100644 --- a/packages/create-instance/create-functional-component.js +++ b/packages/create-instance/create-functional-component.js @@ -6,7 +6,8 @@ import { createSlotVNodes } from './create-slot-vnodes' export default function createFunctionalComponent ( component: Component, - mountingOptions: Options + mountingOptions: Options, + _Vue: Component ): Component { if (mountingOptions.context && typeof mountingOptions.context !== 'object') { throwError('mount.context must be an object') @@ -25,7 +26,7 @@ export default function createFunctionalComponent ( mountingOptions.context.children.map( x => (typeof x === 'function' ? x(h) : x) )) || - createSlotVNodes(h, mountingOptions.slots || {}) + createSlotVNodes(h, mountingOptions.slots || {}, _Vue) ) }, name: component.name, diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 29153660b..3e0e67671 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -40,7 +40,7 @@ export default function createInstance ( (component.options && component.options.functional) || component.functional ) { - component = createFunctionalComponent(component, options) + component = createFunctionalComponent(component, options, _Vue) } else if (options.context) { throwError( `mount.context can only be used when mounting a ` + `functional component` @@ -129,7 +129,7 @@ export default function createInstance ( provide: options.provide, render (h) { const slots = options.slots - ? createSlotVNodes(h, options.slots) + ? createSlotVNodes(h, options.slots, _Vue) : undefined return h( Constructor, diff --git a/packages/create-instance/create-slot-vnodes.js b/packages/create-instance/create-slot-vnodes.js index f3c48aea0..b61f1ac04 100644 --- a/packages/create-instance/create-slot-vnodes.js +++ b/packages/create-instance/create-slot-vnodes.js @@ -10,7 +10,8 @@ function startsWithTag (str: SlotValue): boolean { function createVNodesForSlot ( h: Function, slotValue: SlotValue, - name: string + name: string, + _Vue: any ): VNode | string { if (typeof slotValue === 'string' && !startsWithTag(slotValue)) { return slotValue @@ -22,6 +23,12 @@ function createVNodesForSlot ( let vnode = h(el) if (typeof slotValue === 'string') { const vue = new Vue() + const _vue = new _Vue() + for (const key in _vue._renderProxy) { + if (!(vue._renderProxy[key])) { + vue._renderProxy[key] = _vue._renderProxy[key] + } + } try { // $FlowIgnore vnode = el.render.call(vue._renderProxy, h) @@ -36,15 +43,18 @@ function createVNodesForSlot ( export function createSlotVNodes ( h: Function, - slots: SlotsObject + slots: SlotsObject, + _Vue: any ): Array { return Object.keys(slots).reduce((acc, key) => { const content = slots[key] if (Array.isArray(content)) { - const nodes = content.map(slotDef => createVNodesForSlot(h, slotDef, key)) + const nodes = content.map( + slotDef => createVNodesForSlot(h, slotDef, key, _Vue) + ) return acc.concat(nodes) } - return acc.concat(createVNodesForSlot(h, content, key)) + return acc.concat(createVNodesForSlot(h, content, key, _Vue)) }, []) } diff --git a/test/specs/mounting-options/slots.spec.js b/test/specs/mounting-options/slots.spec.js index d169b971f..3eaad3b67 100644 --- a/test/specs/mounting-options/slots.spec.js +++ b/test/specs/mounting-options/slots.spec.js @@ -5,7 +5,7 @@ import ComponentAsAClass from '~resources/components/component-as-a-class.vue' import ComponentWithParentName from '~resources/components/component-with-parent-name.vue' import { describeWithMountingMethods, vueVersion } from '~resources/utils' import { itSkipIf, itDoNotRunIf } from 'conditional-specs' -import { mount } from '~vue/test-utils' +import { mount, createLocalVue } from '~vue/test-utils' describeWithMountingMethods('options.slots', mountingMethod => { it('mounts component with default slot if passed component in slot object', () => { @@ -575,6 +575,8 @@ describeWithMountingMethods('options.slots', mountingMethod => { mountingMethod.name === 'renderToString', 'sets a component which can access the parent component', () => { + const localVue = createLocalVue() + localVue.prototype.bar = 'FOO' const wrapperComponent = mount( { name: 'parentComponent', @@ -590,12 +592,13 @@ describeWithMountingMethods('options.slots', mountingMethod => { ComponentWithParentName }, slots: { - default: '' - } + default: '' + }, + localVue } ) expect(wrapperComponent.vm.childName).to.equal('component-with-parent-name') - expect(wrapperComponent.html()).to.equal('
quux
') + expect(wrapperComponent.html()).to.equal('
quux
') } ) }) From 1a9dc0a7fef4154afb025162d0a53c24750c3388 Mon Sep 17 00:00:00 2001 From: 38elements Date: Fri, 20 Jul 2018 00:09:11 +0900 Subject: [PATCH 3/9] improve test --- .../components/component-with-parent-name.vue | 7 ++++--- test/specs/mounting-options/slots.spec.js | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/test/resources/components/component-with-parent-name.vue b/test/resources/components/component-with-parent-name.vue index e39fd8cc4..17524d66f 100644 --- a/test/resources/components/component-with-parent-name.vue +++ b/test/resources/components/component-with-parent-name.vue @@ -1,17 +1,18 @@ diff --git a/test/specs/mounting-options/slots.spec.js b/test/specs/mounting-options/slots.spec.js index 3eaad3b67..d6e946e48 100644 --- a/test/specs/mounting-options/slots.spec.js +++ b/test/specs/mounting-options/slots.spec.js @@ -573,17 +573,17 @@ describeWithMountingMethods('options.slots', mountingMethod => { itDoNotRunIf( mountingMethod.name === 'renderToString', - 'sets a component which can access the parent component', + 'sets a component which can access the parent component and the child component', () => { const localVue = createLocalVue() localVue.prototype.bar = 'FOO' - const wrapperComponent = mount( + const ParentComponent = mount( { name: 'parentComponent', template: '
', data () { return { - childName: '' + childComponentName: '' } } }, @@ -592,13 +592,19 @@ describeWithMountingMethods('options.slots', mountingMethod => { ComponentWithParentName }, slots: { - default: '' + default: [ + '', + '' + ] }, localVue } ) - expect(wrapperComponent.vm.childName).to.equal('component-with-parent-name') - expect(wrapperComponent.html()).to.equal('
quux
') + const childComponentName = 'component-with-parent-name' + expect(ParentComponent.vm.childComponentName).to.equal(childComponentName) + expect(ParentComponent.vm.$children.length).to.equal(2) + expect(ParentComponent.vm.$children.every(c => c.$options.name === childComponentName)).to.equal(true) + expect(ParentComponent.html()).to.equal('
FOO,quux
FOO,quux
') } ) }) From 970eac92ac09c4d712fdab7983d81215cf2b38e4 Mon Sep 17 00:00:00 2001 From: 38elements Date: Sun, 22 Jul 2018 16:58:57 +0900 Subject: [PATCH 4/9] add compileTemplateForSlots() --- packages/create-instance/create-instance.js | 13 +++++++++ test/specs/mounting-options/slots.spec.js | 31 +++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 3e0e67671..8d5bb3bb0 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -12,6 +12,17 @@ import { componentNeedsCompiling } from 'shared/validators' import { validateSlots } from './validate-slots' import createScopedSlots from './create-scoped-slots' +function compileTemplateForSlots (slots: Object): void { + Object.keys(slots).forEach(key => { + const slot = Array.isArray(slots[key]) ? slots[key] : [slots[key]] + slot.forEach(slotValue => { + if (componentNeedsCompiling(slotValue)) { + compileTemplate(slotValue) + } + }) + }) +} + export default function createInstance ( component: Component, options: Options, @@ -109,6 +120,8 @@ export default function createInstance ( }) if (options.slots) { + compileTemplateForSlots(options.slots) + // $FlowIgnore validateSlots(options.slots) } diff --git a/test/specs/mounting-options/slots.spec.js b/test/specs/mounting-options/slots.spec.js index d6e946e48..c18ad2c0d 100644 --- a/test/specs/mounting-options/slots.spec.js +++ b/test/specs/mounting-options/slots.spec.js @@ -575,9 +575,10 @@ describeWithMountingMethods('options.slots', mountingMethod => { mountingMethod.name === 'renderToString', 'sets a component which can access the parent component and the child component', () => { + const childComponentName = 'component-with-parent-name' const localVue = createLocalVue() localVue.prototype.bar = 'FOO' - const ParentComponent = mount( + let ParentComponent = mount( { name: 'parentComponent', template: '
', @@ -600,11 +601,37 @@ describeWithMountingMethods('options.slots', mountingMethod => { localVue } ) - const childComponentName = 'component-with-parent-name' expect(ParentComponent.vm.childComponentName).to.equal(childComponentName) expect(ParentComponent.vm.$children.length).to.equal(2) expect(ParentComponent.vm.$children.every(c => c.$options.name === childComponentName)).to.equal(true) expect(ParentComponent.html()).to.equal('
FOO,quux
FOO,quux
') + + ParentComponent = mount( + { + name: 'parentComponent', + template: '
', + data () { + return { + childComponentName: '' + } + } + }, + { + slots: { + default: { + name: childComponentName, + template: '

1234

', + mounted () { + this.$parent.childComponentName = this.$options.name + } + } + } + } + ) + expect(ParentComponent.vm.childComponentName).to.equal(childComponentName) + expect(ParentComponent.vm.$children.length).to.equal(1) + expect(ParentComponent.vm.$children.every(c => c.$options.name === childComponentName)).to.equal(true) + expect(ParentComponent.html()).to.equal('

1234

') } ) }) From 11922f50541f8a05b6b09710cd4dea9db4f2a9f3 Mon Sep 17 00:00:00 2001 From: 38elements Date: Sun, 22 Jul 2018 22:13:01 +0900 Subject: [PATCH 5/9] improve createSlotVNodes --- .../create-functional-component.js | 3 +- packages/create-instance/create-instance.js | 4 +- .../create-instance/create-slot-vnodes.js | 52 ++++++++----------- 3 files changed, 24 insertions(+), 35 deletions(-) diff --git a/packages/create-instance/create-functional-component.js b/packages/create-instance/create-functional-component.js index 38e074b16..188797a9e 100644 --- a/packages/create-instance/create-functional-component.js +++ b/packages/create-instance/create-functional-component.js @@ -7,7 +7,6 @@ import { createSlotVNodes } from './create-slot-vnodes' export default function createFunctionalComponent ( component: Component, mountingOptions: Options, - _Vue: Component ): Component { if (mountingOptions.context && typeof mountingOptions.context !== 'object') { throwError('mount.context must be an object') @@ -26,7 +25,7 @@ export default function createFunctionalComponent ( mountingOptions.context.children.map( x => (typeof x === 'function' ? x(h) : x) )) || - createSlotVNodes(h, mountingOptions.slots || {}, _Vue) + createSlotVNodes(h, mountingOptions.slots || {}, this) ) }, name: component.name, diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 8d5bb3bb0..d60a6f005 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -51,7 +51,7 @@ export default function createInstance ( (component.options && component.options.functional) || component.functional ) { - component = createFunctionalComponent(component, options, _Vue) + component = createFunctionalComponent(component, options) } else if (options.context) { throwError( `mount.context can only be used when mounting a ` + `functional component` @@ -142,7 +142,7 @@ export default function createInstance ( provide: options.provide, render (h) { const slots = options.slots - ? createSlotVNodes(h, options.slots, _Vue) + ? createSlotVNodes(h, options.slots, this) : undefined return h( Constructor, diff --git a/packages/create-instance/create-slot-vnodes.js b/packages/create-instance/create-slot-vnodes.js index b61f1ac04..c49df191c 100644 --- a/packages/create-instance/create-slot-vnodes.js +++ b/packages/create-instance/create-slot-vnodes.js @@ -1,60 +1,50 @@ // @flow -import Vue from 'vue' import { compileToFunctions } from 'vue-template-compiler' -function startsWithTag (str: SlotValue): boolean { - return typeof str === 'string' && str.trim()[0] === '<' -} - function createVNodesForSlot ( h: Function, slotValue: SlotValue, name: string, - _Vue: any + vm: Component ): VNode | string { - if (typeof slotValue === 'string' && !startsWithTag(slotValue)) { - return slotValue - } - - const el = - typeof slotValue === 'string' ? compileToFunctions(slotValue) : slotValue - - let vnode = h(el) + let vnode if (typeof slotValue === 'string') { - const vue = new Vue() - const _vue = new _Vue() - for (const key in _vue._renderProxy) { - if (!(vue._renderProxy[key])) { - vue._renderProxy[key] = _vue._renderProxy[key] - } - } - try { - // $FlowIgnore - vnode = el.render.call(vue._renderProxy, h) - vnode = h(vnode.tag, vnode.data || {}, vnode.children) - } catch (e) { + const el = compileToFunctions(`
${slotValue}{{ }}
`) + const _staticRenderFns = vm._renderProxy.$options.staticRenderFns + // version < 2.5 + if (!vm._renderProxy._staticTrees) { + vm._renderProxy._staticTrees = [] } + vm._renderProxy.$options.staticRenderFns = el.staticRenderFns + vnode = el.render.call(vm._renderProxy, h) + vm._renderProxy.$options.staticRenderFns = _staticRenderFns + vnode = vnode.children[0] + } else { + vnode = h(slotValue) + } + if (vnode.data) { + vnode.data.slot = name + } else { + vnode.data = { slot: name } } - - vnode.data.slot = name return vnode } export function createSlotVNodes ( h: Function, slots: SlotsObject, - _Vue: any + vm: Component ): Array { return Object.keys(slots).reduce((acc, key) => { const content = slots[key] if (Array.isArray(content)) { const nodes = content.map( - slotDef => createVNodesForSlot(h, slotDef, key, _Vue) + slotDef => createVNodesForSlot(h, slotDef, key, vm) ) return acc.concat(nodes) } - return acc.concat(createVNodesForSlot(h, content, key, _Vue)) + return acc.concat(createVNodesForSlot(h, content, key, vm)) }, []) } From 388e2d59b912534c4c70cca465ee12d0307d6672 Mon Sep 17 00:00:00 2001 From: 38elements Date: Sun, 22 Jul 2018 23:24:11 +0900 Subject: [PATCH 6/9] improve style --- packages/create-instance/create-functional-component.js | 2 +- packages/create-instance/create-slot-vnodes.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create-instance/create-functional-component.js b/packages/create-instance/create-functional-component.js index 188797a9e..44bc59bd1 100644 --- a/packages/create-instance/create-functional-component.js +++ b/packages/create-instance/create-functional-component.js @@ -6,7 +6,7 @@ import { createSlotVNodes } from './create-slot-vnodes' export default function createFunctionalComponent ( component: Component, - mountingOptions: Options, + mountingOptions: Options ): Component { if (mountingOptions.context && typeof mountingOptions.context !== 'object') { throwError('mount.context must be an object') diff --git a/packages/create-instance/create-slot-vnodes.js b/packages/create-instance/create-slot-vnodes.js index c49df191c..d6affe2aa 100644 --- a/packages/create-instance/create-slot-vnodes.js +++ b/packages/create-instance/create-slot-vnodes.js @@ -10,7 +10,7 @@ function createVNodesForSlot ( ): VNode | string { let vnode if (typeof slotValue === 'string') { - const el = compileToFunctions(`
${slotValue}{{ }}
`) + const el = compileToFunctions(`
${slotValue}
`) const _staticRenderFns = vm._renderProxy.$options.staticRenderFns // version < 2.5 if (!vm._renderProxy._staticTrees) { From a0d124cd6339bea945da21c34e52a00ac331174d Mon Sep 17 00:00:00 2001 From: 38elements Date: Mon, 23 Jul 2018 00:16:57 +0900 Subject: [PATCH 7/9] add createVNodes() --- .../create-functional-component.js | 2 +- packages/create-instance/create-instance.js | 2 +- .../create-instance/create-slot-vnodes.js | 42 +++++++++++-------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/create-instance/create-functional-component.js b/packages/create-instance/create-functional-component.js index 44bc59bd1..8eb9b88cc 100644 --- a/packages/create-instance/create-functional-component.js +++ b/packages/create-instance/create-functional-component.js @@ -25,7 +25,7 @@ export default function createFunctionalComponent ( mountingOptions.context.children.map( x => (typeof x === 'function' ? x(h) : x) )) || - createSlotVNodes(h, mountingOptions.slots || {}, this) + createSlotVNodes(this, mountingOptions.slots || {}) ) }, name: component.name, diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index d60a6f005..a70f92f6a 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -142,7 +142,7 @@ export default function createInstance ( provide: options.provide, render (h) { const slots = options.slots - ? createSlotVNodes(h, options.slots, this) + ? createSlotVNodes(this, options.slots) : undefined return h( Constructor, diff --git a/packages/create-instance/create-slot-vnodes.js b/packages/create-instance/create-slot-vnodes.js index d6affe2aa..b73bf95b6 100644 --- a/packages/create-instance/create-slot-vnodes.js +++ b/packages/create-instance/create-slot-vnodes.js @@ -2,26 +2,33 @@ import { compileToFunctions } from 'vue-template-compiler' +function createVNodes ( + vm: Component, + slotValue: string +): Array { + const el = compileToFunctions(`
${slotValue}
`) + const _staticRenderFns = vm._renderProxy.$options.staticRenderFns + // version < 2.5 + if (!vm._renderProxy._staticTrees) { + vm._renderProxy._staticTrees = [] + } + vm._renderProxy.$options.staticRenderFns = el.staticRenderFns + const vnode = el.render.call(vm._renderProxy, vm.$createElement) + vm._renderProxy.$options.staticRenderFns = _staticRenderFns + return vnode.children +} + function createVNodesForSlot ( - h: Function, + vm: Component, slotValue: SlotValue, name: string, - vm: Component ): VNode | string { let vnode if (typeof slotValue === 'string') { - const el = compileToFunctions(`
${slotValue}
`) - const _staticRenderFns = vm._renderProxy.$options.staticRenderFns - // version < 2.5 - if (!vm._renderProxy._staticTrees) { - vm._renderProxy._staticTrees = [] - } - vm._renderProxy.$options.staticRenderFns = el.staticRenderFns - vnode = el.render.call(vm._renderProxy, h) - vm._renderProxy.$options.staticRenderFns = _staticRenderFns - vnode = vnode.children[0] + const vnodes = createVNodes(vm, slotValue) + vnode = vnodes[0] } else { - vnode = h(slotValue) + vnode = vm.$createElement(slotValue) } if (vnode.data) { vnode.data.slot = name @@ -32,19 +39,18 @@ function createVNodesForSlot ( } export function createSlotVNodes ( - h: Function, - slots: SlotsObject, - vm: Component + vm: Component, + slots: SlotsObject ): Array { return Object.keys(slots).reduce((acc, key) => { const content = slots[key] if (Array.isArray(content)) { const nodes = content.map( - slotDef => createVNodesForSlot(h, slotDef, key, vm) + slotDef => createVNodesForSlot(vm, slotDef, key) ) return acc.concat(nodes) } - return acc.concat(createVNodesForSlot(h, content, key, vm)) + return acc.concat(createVNodesForSlot(vm, content, key)) }, []) } From 7a896aba75291a78e35b7b1f70afc5592b91fe3b Mon Sep 17 00:00:00 2001 From: 38elements Date: Mon, 23 Jul 2018 01:27:59 +0900 Subject: [PATCH 8/9] add test --- test/specs/mounting-options/slots.spec.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/specs/mounting-options/slots.spec.js b/test/specs/mounting-options/slots.spec.js index c18ad2c0d..fae9c22f0 100644 --- a/test/specs/mounting-options/slots.spec.js +++ b/test/specs/mounting-options/slots.spec.js @@ -223,7 +223,7 @@ describeWithMountingMethods('options.slots', mountingMethod => { } }) - it('mounts component with text slot', () => { + it('mounts component with default and named text slot', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: 'hello,', @@ -237,6 +237,24 @@ describeWithMountingMethods('options.slots', mountingMethod => { } }) + it('mounts functional component with only named text slot', () => { + const TestComponent = { + name: 'component-with-slots', + functional: true, + render: (h, ctx) => h('div', ctx.data, [ctx.slots().default, ctx.slots().footer]) + } + const wrapper = mountingMethod(TestComponent, { + slots: { + footer: 'foo' + } + }) + if (mountingMethod.name === 'renderToString') { + expect(wrapper).contains('foo') + } else { + expect(wrapper.text()).to.contain('foo') + } + }) + it('mounts functional component with text slot', () => { const TestComponent = { name: 'component-with-slots', From b9f425725bf6195ffb91404b6451fe6b2d149df7 Mon Sep 17 00:00:00 2001 From: 38elements Date: Mon, 23 Jul 2018 01:46:26 +0900 Subject: [PATCH 9/9] improve test --- test/specs/mounting-options/slots.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/specs/mounting-options/slots.spec.js b/test/specs/mounting-options/slots.spec.js index fae9c22f0..1c77c69d4 100644 --- a/test/specs/mounting-options/slots.spec.js +++ b/test/specs/mounting-options/slots.spec.js @@ -251,7 +251,7 @@ describeWithMountingMethods('options.slots', mountingMethod => { if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('foo') } else { - expect(wrapper.text()).to.contain('foo') + expect(wrapper.text()).to.equal('foo') } })