Aguardando pelo Resultado de uma Navegação
Quando estiveres a usar o router-link
, a Vue Router chama o router.push
para acionar uma navegação. Enquanto o comportamento esperado para a maioria das ligações é navegar um utilizador para uma nova página, existem algumas situações onde os utilizadores continuarão na mesma página:
- Os utilizadores já estão na página para qual estão a tentar navegar.
- Uma guarda de navegação aborta a navegação fazendo
return false
. - Uma nova guarda de navegação ocorre enquanto a anterior ainda não terminou.
- Uma guarda de navegação redireciona noutro lugar retornando uma nova localização (por exemplo,
return '/login'
). - Uma guarda de navegação lança um
Error
.
Se quisermos fazer alguma coisa depois de uma navegação for terminada, precisamos de uma maneira de esperar depois da chamada de router.push
. Suponha que temos um menu de dispositivo móvel que permite-nos ir para páginas diferentes e apenas queremos esconder o menu assim que tivermos navegado para a nova página, poderemos querer fazer alguma coisa como:
router.push('/my-profile')
this.isMenuOpen = false
router.push('/my-profile')
this.isMenuOpen = false
Mas isto fechará o menu imediatamente porque as navegações são assíncronas, precisamos do wait
para esperar a promessa retornada pelo router.push
:
await router.push('/my-profile')
this.isMenuOpen = false
await router.push('/my-profile')
this.isMenuOpen = false
Agora o menu fechará assim que a navegação for terminada mas também fechará se a navegação foi impedida. Nós precisamos de uma maneira de detetar se realmente mudamos a página em que estamos ou não estamos.
Detetando Falhas de Navegação
Se uma navegação for impedida, resultando em o utilizador continuar na mesma página, o valor resolvido da Promise
retornada pelo router.push
será uma Falha de Navegação. De outro modo, será um valor falso ou melhor falsy
(normalmente undefined
). Isto permite-nos diferenciar o caso de onde navegamos a partir de onde estamos ou não estamos:
const navigationResult = await router.push('/my-profile')
if (navigationResult) {
// navegação impedida
} else {
// navegação bem-sucedida (isto inclui o caso de um redirecionamento)
this.isMenuOpen = false
}
const navigationResult = await router.push('/my-profile')
if (navigationResult) {
// navegação impedida
} else {
// navegação bem-sucedida (isto inclui o caso de um redirecionamento)
this.isMenuOpen = false
}
As falhas de navegação são instâncias de Error
com algumas propriedades adicionais que entregam-nos informações suficiente para saber qual navegação foi impedida e o porquê. Para verificar a natureza de um resultado de navegação, use a função isNavigationFailure
:
import { NavigationFailureType, isNavigationFailure } from 'vue-router'
// tentando sair da página de edição de um artigo sem o guardar
const failure = await router.push('/articles/2')
if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
// mostrar uma pequena notificação para o utilizador
showToast('You have unsaved changes, discard and leave anyway?')
}
import { NavigationFailureType, isNavigationFailure } from 'vue-router'
// tentando sair da página de edição de um artigo sem o guardar
const failure = await router.push('/articles/2')
if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
// mostrar uma pequena notificação para o utilizador
showToast('You have unsaved changes, discard and leave anyway?')
}
Dica
Se omitires o segundo parâmetro: isNavigationFailure(failure)
, ela apenas verifica se failure
é uma Falha de Navegação.
Diferenciando Falhas de Navegação
Conforme dissemos no início, existem situações diferentes que abortam uma navegação, todas elas resultando em diferentes Falhas de Navegação. Eles podem ser diferenciados usando a isNavigationFailure
e o NavigationFailureType
. Existem três tipos diferentes:
aborted
:false
foi retornado dentro de uma guarda de navegação para a navegação.cancelled
: Uma nova navegação ocorreu antes da navegação atual puder terminar, por exemplo, orouter.push
foi chamado enquanto espera dentro de uma guarda de navegação.duplicated
: A navegação foi impedida porque já estamos localização de destino.
Propriedades das Falhas de Navegação
Todas as falhas de navegação expõem as propriedades to
e from
para refletir a localização atual bem como a localização de destino para a navegação que falhou:
// tentando acessar a página de administrador
router.push('/admin').then(failure => {
if (isNavigationFailure(failure, NavigationFailureType.redirected)) {
failure.to.path // '/admin'
failure.from.path // '/'
}
})
// tentando acessar a página de administrador
router.push('/admin').then(failure => {
if (isNavigationFailure(failure, NavigationFailureType.redirected)) {
failure.to.path // '/admin'
failure.from.path // '/'
}
})
Em todos casos, to
e from
são localizações de rota normalizadas.
Detetando Redirecionamentos
Quando estivermos a retornar uma nova localização dentro de uma Guarda de Navegação, estamos a acionar uma nova navegação que se sobrepõe aquela em curso. Diferentemente de outros valores de retorno, um redirecionamento não impede uma navegação, ele cria uma uma nova. Ele é portanto verificado de forma diferente, lendo a propriedade redirectedFrom
em uma Localização de Rota:
await router.push('/my-profile')
if (router.currentRoute.value.redirectedFrom) {
// `redirectedFrom` é uma localização de rota resolvida como `to` e `from` nas guardas de navegação
}
await router.push('/my-profile')
if (router.currentRoute.value.redirectedFrom) {
// `redirectedFrom` é uma localização de rota resolvida como `to` e `from` nas guardas de navegação
}