# Suspense
new
Experimental
Suspense é um novo recurso experimental e a API pode mudar a qualquer momento. Está documentado aqui para que a comunidade possa fornecer feedback sobre a implementação atual.
Não deve ser usado em aplicativos em produção.
# Introdução
É comum que os componentes precisem realizar algum tipo de solicitação assíncrona antes de serem renderizados corretamente. Os componentes geralmente lidam com isso localmente e, em muitos casos, essa é uma abordagem perfeitamente boa.
O componente <suspense>
fornece uma alternativa, permitindo que a espera seja tratada mais adiante na árvore de componentes em vez de em cada componente individual.
Um caso de uso comum envolve componentes assíncronos:
<template>
<suspense>
<template #default>
<todo-list />
</template>
<template #fallback>
<div>
Carregando...
</div>
</template>
</suspense>
</template>
<script>
export default {
components: {
TodoList: defineAsyncComponent(() => import('./TodoList.vue'))
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
O componente <suspense>
tem dois slots. Ambos os slots permitem apenas um nó filho imediato. O nó no slot default
é mostrado se possível. Caso contrário, o nó no slot fallback
será exibido.
Importante, o componente assíncrono não precisa ser o filho imediato do <suspense>
. Ele pode estar em qualquer profundidade dentro da árvore de componentes e não precisa aparecer no mesmo template que o próprio <suspense>
. O conteúdo só é considerado resolvido quando todos os descendentes estiverem prontos.
A outra maneira de acionar o slot fallback
é um componente descendente retornar uma promise de sua função setup
. Isso geralmente é implementado usando async
em vez de retornar explicitamente uma promise:
export default {
async setup() {
// Tenha muito cuidado ao usar `await` dentro de `setup` como
// a maioria das funções da API de Composição só funcionará
// antes do primeiro `await`
const data = await loadData()
// Isso está implicitamente envolvido em uma promise porque
// a função é `assíncrona`
return {
// ...
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# Atualizações em Filhos
Uma vez que um <suspense>
tenha resolvido o conteúdo de seu slot default
, ele só pode ser acionado novamente se o nó raiz default
for substituído. Novos componentes aninhados mais profundamente na árvore não são suficientes para mover o <suspense>
de volta para um estado pendente.
Se o nó raiz mudar, ele acionará o evento pending
. No entanto, por padrão, ele não atualizará o DOM para mostrar o conteúdo fallback
. Em vez disso, ele continuará mostrando o DOM antigo até que os novos componentes estejam prontos. Isso pode ser controlado usando a prop timeout
. Este valor, expresso em milissegundos, diz ao componente <suspense>
quanto tempo esperar antes de mostrar o fallback
. Um valor de 0
irá mostrá-lo imediatamente quando o <suspense>
entrar no estado pendente.
# Eventos
Além do evento pending
, o componente <suspense>
também possui eventos resolve
e fallback
. O evento resolve
é emitido quando o novo conteúdo termina de resolver no slot default
. O evento fallback
é acionado quando o conteúdo do slot fallback
é mostrado.
Os eventos podem ser usados, por exemplo, para mostrar um indicador de carregamento na frente do DOM antigo enquanto novos componentes estão sendo carregados.
# Combinando com Outros Componentes
É comum querer usar <suspense>
em combinação com os componentes <transition>
e <keep-alive>
. A ordem de aninhamento desses componentes é importante para que todos funcionem corretamente.
Além disso, esses componentes são frequentemente usados em conjunto com o componente <router-view>
do Vue Router (opens new window).
O exemplo a seguir mostra como aninhar esses componentes para que todos se comportem conforme o esperado. Para combinações mais simples, você pode remover os componentes desnecessários:
<router-view v-slot="{ Component }">
<template v-if="Component">
<transition mode="out-in">
<keep-alive>
<suspense>
<component :is="Component"></component>
<template #fallback>
<div>
Carregando...
</div>
</template>
</suspense>
</keep-alive>
</transition>
</template>
</router-view>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
O Vue Router tem suporte embutido para carregar componentes preguiçosamente (opens new window) usando importações dinâmicas. Eles são distintos dos componentes assíncronos e atualmente eles não acionarão <suspense>
. No entanto, eles ainda podem ter componentes assíncronos como descendentes e esses podem acionar <suspense>
da maneira usual.