Skip to content

Commit 386cc2c

Browse files
38elementseddyerburgh
authored andcommitted
feat: destructuring slot scope (vuejs#547)
1 parent b7f1635 commit 386cc2c

File tree

3 files changed

+53
-24
lines changed

3 files changed

+53
-24
lines changed

packages/create-instance/create-instance.js

+20-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ import deleteoptions from './delete-mounting-options'
1515
import createFunctionalComponent from './create-functional-component'
1616
import { componentNeedsCompiling } from 'shared/validators'
1717

18+
function isDestructuringSlotScope (slotScope: string): boolean {
19+
return slotScope[0] === '{' && slotScope[slotScope.length - 1] === '}'
20+
}
21+
22+
function getVueTemplateCompilerHelpers (proxy: Object): Object {
23+
const helpers = {}
24+
const names = ['_c', '_o', '_n', '_s', '_l', '_t', '_q', '_i', '_m', '_f', '_k', '_b', '_v', '_e', '_u', '_g']
25+
names.forEach((name) => {
26+
helpers[name] = proxy[name]
27+
})
28+
return helpers
29+
}
30+
1831
export default function createInstance (
1932
component: Component,
2033
options: Options,
@@ -74,12 +87,13 @@ export default function createInstance (
7487
const slotScope = vm.$_vueTestUtils_slotScopes[name]
7588
if (scopedSlotFn) {
7689
props = { ...bindObject, ...props }
77-
const proxy = {}
78-
const helpers = ['_c', '_o', '_n', '_s', '_l', '_t', '_q', '_i', '_m', '_f', '_k', '_b', '_v', '_e', '_u', '_g']
79-
helpers.forEach((key) => {
80-
proxy[key] = vm._renderProxy[key]
81-
})
82-
proxy[slotScope] = props
90+
const helpers = getVueTemplateCompilerHelpers(vm._renderProxy)
91+
let proxy = { ...helpers }
92+
if (isDestructuringSlotScope(slotScope)) {
93+
proxy = { ...helpers, ...props }
94+
} else {
95+
proxy[slotScope] = props
96+
}
8397
return scopedSlotFn.call(proxy)
8498
} else {
8599
return renderSlot.call(vm._renderProxy, name, feedback, props, bindObject)

test/resources/components/component-with-scoped-slots.vue

+15-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
<template>
22
<div>
3-
<div id="foo">
4-
<slot name="foo"
5-
v-for="(item, index) in foo"
6-
:text="item.text"
3+
<div id="destructuring">
4+
<slot name="destructuring"
5+
v-for="(item, index) in items"
6+
:item="item"
77
:index="index">
88
</slot>
99
</div>
10-
<div id="bar">
11-
<slot name="bar"
12-
v-for="(item, index) in bar"
10+
<div id="list">
11+
<slot name="list"
12+
v-for="(item, index) in foo"
1313
:text="item.text"
1414
:index="index">
1515
</slot>
1616
</div>
17+
<div id="single">
18+
<slot name="single" :text="bar"></slot>
19+
</div>
20+
<div id="noProps">
21+
<slot name="noProps"></slot>
22+
</div>
1723
<div id="slots">
1824
<slot></slot>
1925
</div>
@@ -25,8 +31,9 @@
2531
name: 'component-with-scoped-slots',
2632
data () {
2733
return {
34+
items: ['1', '2', '3'],
2835
foo: [{ text: 'a1' }, { text: 'a2' }, { text: 'a3' }],
29-
bar: [{ text: 'A1' }, { text: 'A2' }, { text: 'A3' }]
36+
bar: 'abc'
3037
}
3138
}
3239
}

test/specs/mounting-options/scopedSlots.spec.js

+18-10
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,25 @@ describeWithShallowAndMount('scopedSlots', (mountingMethod) => {
1919
const wrapper = mountingMethod(ComponentWithScopedSlots, {
2020
slots: { default: '<span>123</span>' },
2121
scopedSlots: {
22-
'foo': '<p slot-scope="foo">{{foo.index}},{{foo.text}}</p>',
23-
'bar': '<p slot-scope="bar">{{bar.text}},{{bar.index}}</p>'
22+
destructuring: '<p slot-scope="{ index, item }">{{index}},{{item}}</p>',
23+
list: '<p slot-scope="foo">{{foo.index}},{{foo.text}}</p>',
24+
single: '<p slot-scope="bar">{{bar.text}}</p>',
25+
noProps: '<p slot-scope="baz">baz</p>'
2426
}
2527
})
28+
expect(wrapper.find('#destructuring').html()).to.equal('<div id="destructuring"><p>0,1</p><p>1,2</p><p>2,3</p></div>')
2629
expect(wrapper.find('#slots').html()).to.equal('<div id="slots"><span>123</span></div>')
27-
expect(wrapper.find('#foo').html()).to.equal('<div id="foo"><p>0,a1</p><p>1,a2</p><p>2,a3</p></div>')
28-
expect(wrapper.find('#bar').html()).to.equal('<div id="bar"><p>A1,0</p><p>A2,1</p><p>A3,2</p></div>')
30+
expect(wrapper.find('#list').html()).to.equal('<div id="list"><p>0,a1</p><p>1,a2</p><p>2,a3</p></div>')
31+
expect(wrapper.find('#single').html()).to.equal('<div id="single"><p>abc</p></div>')
32+
expect(wrapper.find('#noProps').html()).to.equal('<div id="noProps"><p>baz</p></div>')
33+
wrapper.vm.items = [4, 5, 6]
2934
wrapper.vm.foo = [{ text: 'b1' }, { text: 'b2' }, { text: 'b3' }]
30-
wrapper.vm.bar = [{ text: 'B1' }, { text: 'B2' }, { text: 'B3' }]
31-
expect(wrapper.find('#foo').html()).to.equal('<div id="foo"><p>0,b1</p><p>1,b2</p><p>2,b3</p></div>')
32-
expect(wrapper.find('#bar').html()).to.equal('<div id="bar"><p>B1,0</p><p>B2,1</p><p>B3,2</p></div>')
35+
wrapper.vm.bar = 'ABC'
36+
expect(wrapper.find('#destructuring').html()).to.equal('<div id="destructuring"><p>0,4</p><p>1,5</p><p>2,6</p></div>')
37+
expect(wrapper.find('#slots').html()).to.equal('<div id="slots"><span>123</span></div>')
38+
expect(wrapper.find('#list').html()).to.equal('<div id="list"><p>0,b1</p><p>1,b2</p><p>2,b3</p></div>')
39+
expect(wrapper.find('#single').html()).to.equal('<div id="single"><p>ABC</p></div>')
40+
expect(wrapper.find('#noProps').html()).to.equal('<div id="noProps"><p>baz</p></div>')
3341
}
3442
)
3543

@@ -38,7 +46,7 @@ describeWithShallowAndMount('scopedSlots', (mountingMethod) => {
3846
const fn = () => {
3947
mountingMethod(ComponentWithScopedSlots, {
4048
scopedSlots: {
41-
'foo': '<template></template>'
49+
single: '<template></template>'
4250
}
4351
})
4452
}
@@ -52,7 +60,7 @@ describeWithShallowAndMount('scopedSlots', (mountingMethod) => {
5260
const fn = () => {
5361
mountingMethod(ComponentWithScopedSlots, {
5462
scopedSlots: {
55-
'foo': '<p slot-scope="foo">{{foo.index}},{{foo.text}}</p>'
63+
list: '<p slot-scope="foo">{{foo.index}},{{foo.text}}</p>'
5664
}
5765
})
5866
}
@@ -70,7 +78,7 @@ describeWithShallowAndMount('scopedSlots', (mountingMethod) => {
7078
const fn = () => {
7179
mountingMethod(ComponentWithScopedSlots, {
7280
scopedSlots: {
73-
'foo': '<p slot-scope="foo">{{foo.index}},{{foo.text}}</p>'
81+
list: '<p slot-scope="foo">{{foo.index}},{{foo.text}}</p>'
7482
}
7583
})
7684
}

0 commit comments

Comments
 (0)