fix(Suspense): emit initial fallback and pending events (#3965)
Fix #3964
This commit is contained in:
parent
43e2a72900
commit
ab6e927041
@ -69,6 +69,70 @@ describe('Suspense', () => {
|
||||
expect(serializeInner(root)).toBe(`<div>async</div>`)
|
||||
})
|
||||
|
||||
test('emits events', async () => {
|
||||
const Async = defineAsyncComponent({
|
||||
render() {
|
||||
return h('div', 'async')
|
||||
}
|
||||
})
|
||||
|
||||
const onFallback = jest.fn()
|
||||
const onResolve = jest.fn()
|
||||
const onPending = jest.fn()
|
||||
|
||||
const show = ref(true)
|
||||
const Comp = {
|
||||
setup() {
|
||||
return () =>
|
||||
h(
|
||||
Suspense,
|
||||
{
|
||||
onFallback,
|
||||
onResolve,
|
||||
onPending,
|
||||
// force displaying the fallback right away
|
||||
timeout: 0
|
||||
},
|
||||
{
|
||||
default: () => (show.value ? h(Async) : null),
|
||||
fallback: h('div', 'fallback')
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
render(h(Comp), root)
|
||||
expect(onFallback).toHaveBeenCalledTimes(1)
|
||||
expect(onPending).toHaveBeenCalledTimes(1)
|
||||
expect(onResolve).toHaveBeenCalledTimes(0)
|
||||
|
||||
await Promise.all(deps)
|
||||
await nextTick()
|
||||
expect(onFallback).toHaveBeenCalledTimes(1)
|
||||
expect(onPending).toHaveBeenCalledTimes(1)
|
||||
expect(onResolve).toHaveBeenCalledTimes(1)
|
||||
|
||||
show.value = false
|
||||
await nextTick()
|
||||
expect(onFallback).toHaveBeenCalledTimes(1)
|
||||
expect(onPending).toHaveBeenCalledTimes(2)
|
||||
expect(onResolve).toHaveBeenCalledTimes(2)
|
||||
|
||||
deps.length = 0
|
||||
show.value = true
|
||||
await nextTick()
|
||||
expect(onFallback).toHaveBeenCalledTimes(2)
|
||||
expect(onPending).toHaveBeenCalledTimes(3)
|
||||
expect(onResolve).toHaveBeenCalledTimes(2)
|
||||
|
||||
await Promise.all(deps)
|
||||
await nextTick()
|
||||
expect(onFallback).toHaveBeenCalledTimes(2)
|
||||
expect(onPending).toHaveBeenCalledTimes(3)
|
||||
expect(onResolve).toHaveBeenCalledTimes(3)
|
||||
})
|
||||
|
||||
test('nested async deps', async () => {
|
||||
const calls: string[] = []
|
||||
|
||||
|
@ -94,6 +94,16 @@ export const Suspense = ((__FEATURE_SUSPENSE__
|
||||
new (): { $props: VNodeProps & SuspenseProps }
|
||||
}
|
||||
|
||||
function triggerEvent(
|
||||
vnode: VNode,
|
||||
name: 'onResolve' | 'onPending' | 'onFallback'
|
||||
) {
|
||||
const eventListener = vnode.props && vnode.props[name]
|
||||
if (isFunction(eventListener)) {
|
||||
eventListener()
|
||||
}
|
||||
}
|
||||
|
||||
function mountSuspense(
|
||||
vnode: VNode,
|
||||
container: RendererElement,
|
||||
@ -137,6 +147,10 @@ function mountSuspense(
|
||||
// now check if we have encountered any async deps
|
||||
if (suspense.deps > 0) {
|
||||
// has async
|
||||
// invoke @fallback event
|
||||
triggerEvent(vnode, 'onPending')
|
||||
triggerEvent(vnode, 'onFallback')
|
||||
|
||||
// mount the fallback tree
|
||||
patch(
|
||||
null,
|
||||
@ -304,10 +318,7 @@ function patchSuspense(
|
||||
} else {
|
||||
// root node toggled
|
||||
// invoke @pending event
|
||||
const onPending = n2.props && n2.props.onPending
|
||||
if (isFunction(onPending)) {
|
||||
onPending()
|
||||
}
|
||||
triggerEvent(n2, 'onPending')
|
||||
// mount pending branch in off-dom container
|
||||
suspense.pendingBranch = newBranch
|
||||
suspense.pendingId++
|
||||
@ -501,10 +512,7 @@ function createSuspenseBoundary(
|
||||
suspense.effects = []
|
||||
|
||||
// invoke @resolve event
|
||||
const onResolve = vnode.props && vnode.props.onResolve
|
||||
if (isFunction(onResolve)) {
|
||||
onResolve()
|
||||
}
|
||||
triggerEvent(vnode, 'onResolve')
|
||||
},
|
||||
|
||||
fallback(fallbackVNode) {
|
||||
@ -521,10 +529,7 @@ function createSuspenseBoundary(
|
||||
} = suspense
|
||||
|
||||
// invoke @fallback event
|
||||
const onFallback = vnode.props && vnode.props.onFallback
|
||||
if (isFunction(onFallback)) {
|
||||
onFallback()
|
||||
}
|
||||
triggerEvent(vnode, 'onFallback')
|
||||
|
||||
const anchor = next(activeBranch!)
|
||||
const mountFallback = () => {
|
||||
|
Loading…
Reference in New Issue
Block a user