mirror of https://github.com/vuejs/core.git
fix(runtime-vapor): render slot fallback if slot content is not a valid block
close #13668
This commit is contained in:
parent
56a7f9dd18
commit
8602be22fd
|
@ -502,5 +502,64 @@ describe('component: slots', () => {
|
|||
await nextTick()
|
||||
expect(host.innerHTML).toBe('<div><h1></h1><!--slot--></div>')
|
||||
})
|
||||
|
||||
test('render fallback when slot content is not valid', async () => {
|
||||
const Child = {
|
||||
setup() {
|
||||
return createSlot('default', null, () =>
|
||||
document.createTextNode('fallback'),
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
const { html } = define({
|
||||
setup() {
|
||||
return createComponent(Child, null, {
|
||||
default: () => {
|
||||
return template('<!--comment-->')()
|
||||
},
|
||||
})
|
||||
},
|
||||
}).render()
|
||||
|
||||
expect(html()).toBe('fallback<!--slot-->')
|
||||
})
|
||||
|
||||
test('render fallback when v-if condition is false', async () => {
|
||||
const Child = {
|
||||
setup() {
|
||||
return createSlot('default', null, () =>
|
||||
document.createTextNode('fallback'),
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
const toggle = ref(false)
|
||||
|
||||
const { html } = define({
|
||||
setup() {
|
||||
return createComponent(Child, null, {
|
||||
default: () => {
|
||||
return createIf(
|
||||
() => toggle.value,
|
||||
() => {
|
||||
return document.createTextNode('content')
|
||||
},
|
||||
)
|
||||
},
|
||||
})
|
||||
},
|
||||
}).render()
|
||||
|
||||
expect(html()).toBe('fallback<!--if--><!--slot-->')
|
||||
|
||||
toggle.value = true
|
||||
await nextTick()
|
||||
expect(html()).toBe('content<!--if--><!--slot-->')
|
||||
|
||||
toggle.value = false
|
||||
await nextTick()
|
||||
expect(html()).toBe('fallback<!--if--><!--slot-->')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
import { EMPTY_OBJ, NO, hasOwn, isArray, isFunction } from '@vue/shared'
|
||||
import { type Block, type BlockFn, DynamicFragment, insert } from './block'
|
||||
import {
|
||||
type Block,
|
||||
type BlockFn,
|
||||
DynamicFragment,
|
||||
insert,
|
||||
isValidBlock,
|
||||
} from './block'
|
||||
import { rawPropsProxyHandlers } from './componentProps'
|
||||
import { currentInstance, isRef } from '@vue/runtime-dom'
|
||||
import type { LooseRawProps, VaporComponentInstance } from './component'
|
||||
|
@ -126,6 +132,7 @@ export function createSlot(
|
|||
const renderSlot = () => {
|
||||
const slot = getSlot(rawSlots, isFunction(name) ? name() : name)
|
||||
if (slot) {
|
||||
fragment.fallback = fallback
|
||||
// create and cache bound version of the slot to make it stable
|
||||
// so that we avoid unnecessary updates if it resolves to the same slot
|
||||
fragment.update(
|
||||
|
@ -133,7 +140,13 @@ export function createSlot(
|
|||
(slot._bound = () => {
|
||||
const slotContent = slot(slotProps)
|
||||
if (slotContent instanceof DynamicFragment) {
|
||||
slotContent.fallback = fallback
|
||||
// render fallback if slot content is not a valid block
|
||||
if (
|
||||
(slotContent.fallback = fallback) &&
|
||||
!isValidBlock(slotContent.nodes)
|
||||
) {
|
||||
slotContent.update(fallback)
|
||||
}
|
||||
}
|
||||
return slotContent
|
||||
}),
|
||||
|
|
Loading…
Reference in New Issue