mirror of
https://github.com/vuejs/vue.git
synced 2024-11-22 04:39:46 +00:00
fix: template v-slot should work with v-else conditions
This commit is contained in:
parent
5851961ca3
commit
2807fd24b0
@ -366,53 +366,27 @@ function genScopedSlots (
|
||||
})
|
||||
return `scopedSlots:_u([${
|
||||
Object.keys(slots).map(key => {
|
||||
return genScopedSlot(key, slots[key], state)
|
||||
return genScopedSlot(slots[key], state)
|
||||
}).join(',')
|
||||
}]${hasDynamicKeys ? `,true` : ``})`
|
||||
}
|
||||
|
||||
function genScopedSlot (
|
||||
key: string,
|
||||
el: ASTElement,
|
||||
state: CodegenState
|
||||
): string {
|
||||
if (el.if && !el.ifProcessed) {
|
||||
return genIfScopedSlot(key, el, state)
|
||||
return genIf(el, state, genScopedSlot, `null`)
|
||||
}
|
||||
if (el.for && !el.forProcessed) {
|
||||
return genForScopedSlot(key, el, state)
|
||||
return genFor(el, state, genScopedSlot)
|
||||
}
|
||||
const fn = `function(${String(el.slotScope)}){` +
|
||||
`return ${el.tag === 'template'
|
||||
? genChildren(el, state) || 'undefined'
|
||||
: genElement(el, state)
|
||||
}}`
|
||||
return `{key:${key},fn:${fn}}`
|
||||
}
|
||||
|
||||
function genIfScopedSlot (
|
||||
key: string,
|
||||
el: any,
|
||||
state: CodegenState
|
||||
): string {
|
||||
el.ifProcessed = true
|
||||
return `(${el.if})?${genScopedSlot(key, el, state)}:null`
|
||||
}
|
||||
|
||||
function genForScopedSlot (
|
||||
key: string,
|
||||
el: any,
|
||||
state: CodegenState
|
||||
): string {
|
||||
const exp = el.for
|
||||
const alias = el.alias
|
||||
const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''
|
||||
const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''
|
||||
el.forProcessed = true // avoid recursion
|
||||
return `_l((${exp}),` +
|
||||
`function(${alias}${iterator1}${iterator2}){` +
|
||||
`return ${genScopedSlot(key, el, state)}` +
|
||||
'})'
|
||||
return `{key:${el.slotTarget || `"default"`},fn:${fn}}`
|
||||
}
|
||||
|
||||
export function genChildren (
|
||||
|
@ -107,6 +107,7 @@ export function parse (
|
||||
}
|
||||
|
||||
function closeElement (element) {
|
||||
trimEndingWhitespace(element)
|
||||
if (!inVPre && !element.processed) {
|
||||
element = processElement(element, options)
|
||||
}
|
||||
@ -133,14 +134,25 @@ export function parse (
|
||||
if (currentParent && !element.forbidden) {
|
||||
if (element.elseif || element.else) {
|
||||
processIfConditions(element, currentParent)
|
||||
} else if (element.slotScope) { // scoped slot
|
||||
const name = element.slotTarget || '"default"'
|
||||
;(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element
|
||||
} else {
|
||||
if (element.slotScope) {
|
||||
// scoped slot
|
||||
// keep it in the children list so that v-else(-if) conditions can
|
||||
// find it as the prev node.
|
||||
const name = element.slotTarget || '"default"'
|
||||
;(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element
|
||||
}
|
||||
currentParent.children.push(element)
|
||||
element.parent = currentParent
|
||||
}
|
||||
}
|
||||
|
||||
// final children cleanup
|
||||
// filter out scoped slots
|
||||
element.children = element.children.filter(c => !c.slotScope)
|
||||
// remove trailing whitespace node again
|
||||
trimEndingWhitespace(element)
|
||||
|
||||
// check pre state
|
||||
if (element.pre) {
|
||||
inVPre = false
|
||||
@ -154,6 +166,20 @@ export function parse (
|
||||
}
|
||||
}
|
||||
|
||||
function trimEndingWhitespace (el) {
|
||||
// remove trailing whitespace node
|
||||
if (!inPre) {
|
||||
let lastNode
|
||||
while (
|
||||
(lastNode = el.children[el.children.length - 1]) &&
|
||||
lastNode.type === 3 &&
|
||||
lastNode.text === ' '
|
||||
) {
|
||||
el.children.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkRootConstraints (el) {
|
||||
if (el.tag === 'slot' || el.tag === 'template') {
|
||||
warnOnce(
|
||||
@ -268,13 +294,6 @@ export function parse (
|
||||
|
||||
end (tag, start, end) {
|
||||
const element = stack[stack.length - 1]
|
||||
if (!inPre) {
|
||||
// remove trailing whitespace node
|
||||
const lastNode = element.children[element.children.length - 1]
|
||||
if (lastNode && lastNode.type === 3 && lastNode.text === ' ') {
|
||||
element.children.pop()
|
||||
}
|
||||
}
|
||||
// pop stack
|
||||
stack.length -= 1
|
||||
currentParent = stack[stack.length - 1]
|
||||
@ -658,8 +677,9 @@ function processSlotContent (el) {
|
||||
const slots = el.scopedSlots || (el.scopedSlots = {})
|
||||
const { name, dynamic } = getSlotName(slotBinding)
|
||||
const slotContainer = slots[name] = createASTElement('template', [], el)
|
||||
slotContainer.slotTarget = name
|
||||
slotContainer.slotTargetDynamic = dynamic
|
||||
slotContainer.children = el.children
|
||||
slotContainer.children = el.children.filter(c => !c.slotScope)
|
||||
slotContainer.slotScope = slotBinding.value || `_`
|
||||
// remove children as they are returned from scopedSlots now
|
||||
el.children = []
|
||||
|
@ -827,6 +827,24 @@ describe('Component scoped slot', () => {
|
||||
expect(vm.$el.innerHTML.replace(/\s+/g, ' ')).toMatch(`b from foo one a from foo two `)
|
||||
}).then(done)
|
||||
})
|
||||
|
||||
it('should work with v-if/v-else', done => {
|
||||
const vm = new Vue({
|
||||
data: { flag: true },
|
||||
template: `
|
||||
<foo>
|
||||
<template v-if="flag" v-slot:one="one">a {{ one }} </template>
|
||||
<template v-else v-slot:two="two">b {{ two }} </template>
|
||||
</foo>
|
||||
`,
|
||||
components: { Foo }
|
||||
}).$mount()
|
||||
expect(vm.$el.innerHTML).toBe(`a from foo one `)
|
||||
vm.flag = false
|
||||
waitForUpdate(() => {
|
||||
expect(vm.$el.innerHTML).toBe(`b from foo two `)
|
||||
}).then(done)
|
||||
})
|
||||
})
|
||||
|
||||
// 2.6 scoped slot perf optimization
|
||||
|
Loading…
Reference in New Issue
Block a user