You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/api/built-in-components.md
+4Lines changed: 4 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -318,6 +318,7 @@ Used for orchestrating nested async dependencies in a component tree.
318
318
```ts
319
319
interfaceSuspenseProps {
320
320
timeout?:string|number
321
+
suspensible?:boolean
321
322
}
322
323
```
323
324
@@ -333,4 +334,7 @@ Used for orchestrating nested async dependencies in a component tree.
333
334
334
335
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.
335
336
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)
Copy file name to clipboardExpand all lines: src/guide/built-ins/suspense.md
+34Lines changed: 34 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -133,6 +133,40 @@ The following example shows how to nest these components so that they all behave
133
133
134
134
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.
135
135
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.
0 commit comments