Skip to content

Commit c1de1dd

Browse files
authored
feat(Suspense): add suspensible prop information (#2785)
Signed-off-by: GitHub <noreply@github.com>
1 parent d3c861b commit c1de1dd

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

src/api/built-in-components.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ Used for orchestrating nested async dependencies in a component tree.
318318
```ts
319319
interface SuspenseProps {
320320
timeout?: string | number
321+
suspensible?: boolean
321322
}
322323
```
323324

@@ -333,4 +334,7 @@ Used for orchestrating nested async dependencies in a component tree.
333334

334335
If it encounters async dependencies ([Async Components](/guide/components/async) and components with [`async setup()`](/guide/built-ins/suspense#async-setup)) while rendering the default slot, it will wait until all of them are resolved before displaying the default slot.
335336

337+
By setting the Suspense as `suspensible`, all the async dependency handling
338+
will be handled by the parent Suspense. See [implementation details](https://github.com/vuejs/core/pull/6736)
339+
336340
- **See also** [Guide - Suspense](/guide/built-ins/suspense)

src/guide/built-ins/suspense.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,40 @@ The following example shows how to nest these components so that they all behave
133133

134134
Vue Router has built-in support for [lazily loading components](https://router.vuejs.org/guide/advanced/lazy-loading.html) using dynamic imports. These are distinct from async components and currently they will not trigger `<Suspense>`. However, they can still have async components as descendants and those can trigger `<Suspense>` in the usual way.
135135

136+
## Nested Suspense
137+
138+
When we have multiple async components (common for nested or layout-based routes) like this:
139+
140+
```vue-html
141+
<Suspense>
142+
<component :is="DynamicAsyncOuter">
143+
<component :is="DynamicAsyncInner" />
144+
</component>
145+
</Suspense>
146+
```
147+
148+
`<Suspense>` creates a boundary that will resolve all the async components down the tree,
149+
as expected. However, when we change `DynamicAsyncOuter`, `<Suspense>` awaits it correctly, but when we change `DynamicAsyncInner`,
150+
the nested `DynamicAsyncInner` renders an empty node until it has been resolved (instead of the previous one or fallback slot).
151+
152+
In order to solve that, we could have a nested suspense to handle the patch for the nested component, like:
153+
154+
```vue-html
155+
<Suspense>
156+
<component :is="DynamicAsyncOuter">
157+
<Suspense suspensible> <!-- this -->
158+
<component :is="DynamicAsyncInner" />
159+
</Suspense>
160+
</component>
161+
</Suspense>
162+
```
163+
164+
If you don't set the `suspensible` prop, the inner `<Suspense>` will be treated like a sync component by the parent `<Suspense>`.
165+
That means that it has its own fallback slot and if both `Dynamic` components change at the same time,
166+
there might be empty nodes and multiple patching cycles while the child `<Suspense>` is loading its own dependency tree,
167+
which might not be desirable. When it's set, all the async dependency handling is given to the parent `<Suspense>` (including the events emitted)
168+
and the inner `<Suspense>` serves solely as another boundary for the dependency resolution and patching.
169+
136170
---
137171

138172
**Related**

0 commit comments

Comments
 (0)