fix: should consider presence of normal slots when caching normalized scoped slots

fix #9644
This commit is contained in:
Evan You 2019-03-09 02:03:19 +08:00
parent da77d6a98b
commit 9313cf9174
2 changed files with 41 additions and 1 deletions

View File

@ -11,6 +11,7 @@ export function normalizeScopedSlots (
): any { ): any {
let res let res
const isStable = slots ? !!slots.$stable : true const isStable = slots ? !!slots.$stable : true
const hasNormalSlots = Object.keys(normalSlots).length > 0
const key = slots && slots.$key const key = slots && slots.$key
if (!slots) { if (!slots) {
res = {} res = {}
@ -22,7 +23,8 @@ export function normalizeScopedSlots (
prevSlots && prevSlots &&
prevSlots !== emptyObject && prevSlots !== emptyObject &&
key === prevSlots.$key && key === prevSlots.$key &&
Object.keys(normalSlots).length === 0 !hasNormalSlots &&
!prevSlots.$hasNormal
) { ) {
// fast path 2: stable scoped slots w/ no normal slots to proxy, // fast path 2: stable scoped slots w/ no normal slots to proxy,
// only need to normalize once // only need to normalize once
@ -48,6 +50,7 @@ export function normalizeScopedSlots (
} }
def(res, '$stable', isStable) def(res, '$stable', isStable)
def(res, '$key', key) def(res, '$key', key)
def(res, '$hasNormal', hasNormalSlots)
return res return res
} }

View File

@ -1227,4 +1227,41 @@ describe('Component scoped slot', () => {
expect(vm.$el.textContent.trim()).toBe(`2`) expect(vm.$el.textContent.trim()).toBe(`2`)
}).then(done) }).then(done)
}) })
// #9644
it('should factor presence of normal slots into scoped slots caching', done => {
const Wrapper = {
template: `<div>
<p>Default:<slot/></p>
<p>Content:<slot name='content'/></p>
</div>`
}
const vm = new Vue({
data: { ok: false },
components: { Wrapper },
template: `<wrapper>
<p v-if='ok'>ok</p>
<template #content>
<p v-if='ok'>ok</p>
</template>
</wrapper>`
}).$mount()
expect(vm.$el.textContent).not.toMatch(`Default:ok`)
expect(vm.$el.textContent).not.toMatch(`Content:ok`)
vm.ok = true
waitForUpdate(() => {
expect(vm.$el.textContent).toMatch(`Default:ok`)
expect(vm.$el.textContent).toMatch(`Content:ok`)
vm.ok = false
}).then(() => {
expect(vm.$el.textContent).not.toMatch(`Default:ok`)
expect(vm.$el.textContent).not.toMatch(`Content:ok`)
vm.ok = true
}).then(() => {
expect(vm.$el.textContent).toMatch(`Default:ok`)
expect(vm.$el.textContent).toMatch(`Content:ok`)
}).then(done)
})
}) })