Skip to content

Commit

Permalink
fix: fix scopedSlots regression
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Jun 6, 2022
1 parent 642e7aa commit 4f2a04e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 19 deletions.
3 changes: 2 additions & 1 deletion src/core/instance/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ export function renderMixin(Vue: typeof Component) {
vm.$scopedSlots = normalizeScopedSlots(
vm.$parent!,
_parentVnode.data!.scopedSlots,
vm.$slots
vm.$slots,
vm.$scopedSlots
)
if (vm._slotsProxy) {
syncSetupSlots(vm._slotsProxy, vm.$scopedSlots)
Expand Down
41 changes: 23 additions & 18 deletions src/core/vdom/helpers/normalize-scoped-slots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,40 @@ import { currentInstance, setCurrentInstance } from 'v3/currentInstance'

export function normalizeScopedSlots(
ownerVm: Component,
slots: { [key: string]: Function } | void,
normalSlots: { [key: string]: VNode[] }
scopedSlots: { [key: string]: Function } | undefined,
normalSlots: { [key: string]: VNode[] },
prevScopedSlots?: { [key: string]: Function }
): any {
let res
const prevSlots = ownerVm.$scopedSlots
const hasNormalSlots = Object.keys(normalSlots).length > 0
const isStable = slots ? !!slots.$stable : !hasNormalSlots
const key = slots && slots.$key
if (!slots) {
const isStable = scopedSlots ? !!scopedSlots.$stable : !hasNormalSlots
const key = scopedSlots && scopedSlots.$key
if (!scopedSlots) {
res = {}
} else if (slots._normalized) {
} else if (scopedSlots._normalized) {
// fast path 1: child component re-render only, parent did not change
return slots._normalized
return scopedSlots._normalized
} else if (
isStable &&
prevSlots &&
prevSlots !== emptyObject &&
key === prevSlots.$key &&
prevScopedSlots &&
prevScopedSlots !== emptyObject &&
key === prevScopedSlots.$key &&
!hasNormalSlots &&
!prevSlots.$hasNormal
!prevScopedSlots.$hasNormal
) {
// fast path 2: stable scoped slots w/ no normal slots to proxy,
// only need to normalize once
return prevSlots
return prevScopedSlots
} else {
res = {}
for (const key in slots) {
if (slots[key] && key[0] !== '$') {
res[key] = normalizeScopedSlot(ownerVm, normalSlots, key, slots[key])
for (const key in scopedSlots) {
if (scopedSlots[key] && key[0] !== '$') {
res[key] = normalizeScopedSlot(
ownerVm,
normalSlots,
key,
scopedSlots[key]
)
}
}
}
Expand All @@ -48,8 +53,8 @@ export function normalizeScopedSlots(
}
// avoriaz seems to mock a non-extensible $scopedSlots object
// and when that is passed down this would cause an error
if (slots && Object.isExtensible(slots)) {
slots._normalized = res
if (scopedSlots && Object.isExtensible(scopedSlots)) {
scopedSlots._normalized = res
}
def(res, '$stable', isStable)
def(res, '$key', key)
Expand Down
29 changes: 29 additions & 0 deletions test/unit/features/component/component-slot.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1044,4 +1044,33 @@ describe('Component slot', () => {

expect(vm.$el.innerHTML).toBe(`<!----><span>b</span>`)
})

// regression 2.7.0-alpha.4
it('passing scoped slots through nested parent chain', () => {
const Foo = {
template: `
<div><slot>foo default</slot></div>
`
}

const Bar = {
components: { Foo },
template: `<Foo><slot name="bar"/></Foo>`
}

const App = {
components: { Bar },
template: `<Bar>
<template #bar>
<span>App content for Bar#bar</span>
</template>
</Bar>`
}

const vm = new Vue({
render: h => h(App)
}).$mount()

expect(vm.$el.innerHTML).toMatch(`App content for Bar#bar`)
})
})

0 comments on commit 4f2a04e

Please sign in to comment.