Skip to content

Commit 0ccefff

Browse files
committed
support v-for on scoped slots (fix vuejs#5615)
1 parent dc00590 commit 0ccefff

File tree

5 files changed

+60
-7
lines changed

5 files changed

+60
-7
lines changed

flow/component.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ declare interface Component {
106106
// check custom keyCode
107107
_k: (eventKeyCode: number, key: string, builtInAlias: number | Array<number> | void) => boolean;
108108
// resolve scoped slots
109-
_u: (scopedSlots: Array<[string, Function]>) => { [key: string]: Function };
109+
_u: (scopedSlots: ScopedSlotsData, res?: Object) => { [key: string]: Function };
110110

111111
// allow dynamic method registration
112112
[key: string]: any

flow/vnode.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,6 @@ declare type VNodeDirective = {
7171
arg?: string;
7272
modifiers?: ASTModifiers;
7373
def?: Object;
74-
}
74+
};
75+
76+
declare type ScopedSlotsData = Array<{ key: string, fn: Function } | ScopedSlotsData>;

src/compiler/codegen/index.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,26 @@ function genScopedSlots (slots: { [key: string]: ASTElement }): string {
298298
}
299299

300300
function genScopedSlot (key: string, el: ASTElement) {
301-
return `[${key},function(${String(el.attrsMap.scope)}){` +
301+
if (el.for && !el.forProcessed) {
302+
return genForScopedSlot(key, el)
303+
}
304+
return `{key:${key},fn:function(${String(el.attrsMap.scope)}){` +
302305
`return ${el.tag === 'template'
303306
? genChildren(el) || 'void 0'
304307
: genElement(el)
305-
}}]`
308+
}}}`
309+
}
310+
311+
function genForScopedSlot (key: string, el: any) {
312+
const exp = el.for
313+
const alias = el.alias
314+
const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''
315+
const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''
316+
el.forProcessed = true // avoid recursion
317+
return `_l((${exp}),` +
318+
`function(${alias}${iterator1}${iterator2}){` +
319+
`return ${genScopedSlot(key, el)}` +
320+
'})'
306321
}
307322

308323
function genChildren (el: ASTElement, checkSkip?: boolean): string | void {

src/core/instance/render-helpers/resolve-slots.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,16 @@ function isWhitespace (node: VNode): boolean {
4242
}
4343

4444
export function resolveScopedSlots (
45-
fns: Array<[string, Function]>
45+
fns: ScopedSlotsData, // see flow/vnode
46+
res?: Object
4647
): { [key: string]: Function } {
47-
const res = {}
48+
res = res || {}
4849
for (let i = 0; i < fns.length; i++) {
49-
res[fns[i][0]] = fns[i][1]
50+
if (Array.isArray(fns[i])) {
51+
resolveScopedSlots(fns[i], res)
52+
} else {
53+
res[fns[i].key] = fns[i].fn
54+
}
5055
}
5156
return res
5257
}

test/unit/features/component/component-scoped-slot.spec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,35 @@ describe('Component scoped slot', () => {
382382
}).$mount()
383383
expect(vm.$el.innerHTML).toBe('<span>hello</span>')
384384
})
385+
386+
// #5615
387+
it('scoped slot with v-for', done => {
388+
const vm = new Vue({
389+
data: { names: ['foo', 'bar'] },
390+
template: `
391+
<test ref="test">
392+
<template v-for="n in names" :slot="n" scope="props">
393+
<span>{{ props.msg }}</span>
394+
</template>
395+
</test>
396+
`,
397+
components: {
398+
test: {
399+
data: () => ({ msg: 'hello' }),
400+
template: `
401+
<div>
402+
<slot name="foo" :msg="msg + ' foo'"></slot>
403+
<slot name="bar" :msg="msg + ' bar'"></slot>
404+
</div>
405+
`
406+
}
407+
}
408+
}).$mount()
409+
410+
expect(vm.$el.innerHTML).toBe('<span>hello foo</span> <span>hello bar</span>')
411+
vm.$refs.test.msg = 'world'
412+
waitForUpdate(() => {
413+
expect(vm.$el.innerHTML).toBe('<span>world foo</span> <span>world bar</span>')
414+
}).then(done)
415+
})
385416
})

0 commit comments

Comments
 (0)